今天晚上参加了《算法实践课程》的期末测验。
作为半吊子的废物ACMer,课程学习的内容以及测验的内容着实十分简单。
但是,自己太久没有敲代码、不端正的态度、薄弱的技术功底、废物的数学思维,导致即使是这么简单的题目,我也没有做到快速的20分钟A一题的速度。我觉得自己需要反省,总结自己失败的原因,顺便贴一下自己的代码吧。
考题与答题情况:
第一题:一毛一样除了题面和故事改了一下,就是一道赤裸的01背包问题。但是写完代码,WA了一发。
第二题:从小到大输出N皇后的解,一道非常基础的DFS问题。WA了一发。
第三题:一道很简单的BFS问题,输出最小解的值。
错误原因:
第一题: 背包问题要尽量写成,下标从1开始,否则写递推式的时候,循环里面的j-1部分就不好写,容易有错误。
以及如果这么写,输入数据的下标也是从1始,我错就错在这两点上。下标习惯从0开始计数了,还没加特判。。。
第二题: 数学没学好。八皇后上下左右判断很简单,只需要判断两个点是x1!=x2&&y1!=y2即可。
但是斜着的判断,更方便的判断方法是 abs(x1-x2)!=abs(y1-y2)
而我错误的写法是,abs(x1-y1)!=abs(x2-y2) ,就这一个错误,搞得要死要活。
第三题还好,没错就A了。但是我用的是DFS,而不是最应该想到的BFS。可能还是我思维僵硬,DFS用的太多了,这样对于BFS类的问题就不够活跃。
失败折射:
失败不是说我没有AC。我觉得失败的原因是,我AC的不够快,思维不够强,编码能下降太多,对自己的要求也下降了太多。今天晚上只是从非常简单的算法题角度,以编码的方式给我敲响了警钟。
虽然说距离当初的训练刷题时间已经过去1年多了,但是很多基础的东西自己那么快就忘了就是不应该的。作为计算机专业的学生,还是要多加以学习新知识、温习活知识、巩固旧知识呐。
接下来是本次题目的题面:
第一题:
Description
小K是个苦命的孩子,他的师傅为了多赚钱,以减肥为理由,让他去采药,并说不完成不能吃饭。野地里有许多不同的草药,采每一株都需要一些时间,每一株也有它自身的价值。要求在规定的时间t里,采到的草药的总价值最大。
Input
第一行有2个整数T(1≤T≤1000)和M(1≤M≤100),一个空格隔开,T代表总共能够用来采药的时间,M代表山洞里的草药的数目。
接下来的M行每行包括两个在1到100之间包括1和100)的整数,分别表示采摘某株草药的时间和这株草药的价值。
Output
1个整数,表示在规定的时间内可以采到的草药的最大总价值。
Sample Input
70 371 10069 11 2
Sample Output
3
个人AC代码(01背包):
#include<bits/stdc++.h>
#include<algorithm>
using namespace std;
#define inf 999
#define loop(x,y,z) for(x=y;x<z;x++)
int n,m;//n是个数,m是背包
int dp[inf][1200];
struct Node
{
int v,cost;
}node[inf];;
void input()
{
scanf("%d%d",&m,&n);
int i;
loop(i,1,n+1)
scanf("%d%d",&node[i].cost,&node[i].v);
}
void cal_ans()
{
memset(dp,0,sizeof dp);
int i,j;
loop(i,1,m+1)
loop(j,1,n+1)
{
dp[i][j]=dp[i][j-1];
if(i-node[j].cost>=0)
dp[i][j]=max(dp[i][j-1],dp[i-node[j].cost][j-1]+node[j].v);
}
}
void output()
{
printf("%d\n",dp[m][n]);
}
int main()
{
input();
cal_ans();
output();
return 0;
}
第二题:
Description
N皇后的排列,每行一个不冲突;N<=13。
Input
一个数字N (6 <= N <= 13) 表示棋盘是N x N大小的。
Output
前三行为前三个解,每个解的两个数字之间用一个空格隔开。第四行只有一个数字,表示解的总数。
解的输出顺序为从上到下从左到右,小的优先输出
Sample Input
6
Sample Output
2 4 6 1 3 53 6 2 5 1 44 1 5 2 6 34
个人AC代码(DFS):
#include<bits/stdc++.h>
#include<algorithm>
using namespace std;
#define inf 15
#define INF 999999999
#define loop(x,y,z) for(x=y;x<z;x++)
//下标从0始
int n,sum;
int e[inf];//搜索使用的数组
struct Node
{
int ans[inf];
void print()
{
int i;
loop(i,0,n-1)
printf("%d ",ans[i]+1);
printf("%d\n",ans[i]+1);
}
void set()
{
int i;
loop(i,0,n)
ans[i]=e[i];
}
}Ans[5000];
void input()
{
scanf("%d",&n);
memset(Ans,0,sizeof Ans);//初始化
sum=0;
}
bool isLegal(int x1,int y1)//皇后位置是否合法
{
int i;
loop(i,0,x1)
{
int x2=i;
int y2=e[i];
if(x1==x2||y1==y2||abs(x1-x2)==abs(y1-y2))//数学要好好学
return false;
}
return true;
}
void dfs(int i)//第v行
{
if(i==n)//终止
{
if(sum<5)
Ans[sum].set();
sum++;
return ;
}
//否则
int j;
loop(j,0,n)
{
if(isLegal(i,j))//如果在此行可放
{
e[i]=j;
dfs(i+1);//下一行
}
}
}
void output()
{
int i;
loop(i,0,3)
{
Ans[i].print();
}
printf("%d\n",sum);
}
int main()
{
input();
dfs(0);
output();
return 0;
}
第三题:
Description
Input
Output
一行,即最少按键次数;若无法到达,则输出−1。
Sample Input
5 1 5 3 3 1 2 5
Sample Output
3
个人AC代码(DFS):
#include<bits/stdc++.h>
#include<algorithm>
using namespace std;
#define inf 250
#define INF 999999999
#define loop(x,y,z) for(x=y;x<z;x++)
//下标从1开始
int n,a,b;
int e[inf];//输入
int book[inf];//标记楼层
int ans;
void input()
{
scanf("%d%d%d",&n,&a,&b);
int i;
loop(i,1,n+1)
scanf("%d",&e[i]);
ans=INF;//初始化
memset(book,0,sizeof book);
}
void dfs(int v,int cost)
{
if(cost>ans||book[v])return;//剪枝:无意义或者走过
if(v==b)//到达目的地
{
ans=min(ans,cost);
return;
}
//如果未走过
book[v]=1;
//向上走
if(v+e[v]<=n)
dfs(v+e[v],cost+1);
//向下走
if(v-e[v]>=1)
dfs(v-e[v],cost+1);
}
void output()
{
if(ans==INF)
printf("-1\n");
else
printf("%d\n",ans);
}
int main()
{
input();
dfs(a,0);//从a开始,耗费为0
output();
return 0;
}
#include<bits/stdc++.h>
using namespace std;
int e[300];
int book[300];
int n,a,b;
struct Node
{
int order;
int value;
Node(int v,int o):value(v),order(o)
{
}
};
int main()
{
scanf("%d%d%d",&n,&a,&b);
for(int i=1;i<=n;i++)
scanf("%d",&e[i]);
memset(book,0,sizeof book);
queue<Node>q;
while(!q.empty())q.pop();
q.push(Node(a,0));//起点
while(!q.empty())
{
Node v=q.front();
q.pop();
book[v.value]=1;
if(v.value==b)
{
printf("%d\n",v.order);
break;
}
//up
int u=v.value+e[v.value];
if(u<=n&&!book[u])
{
book[u]=1;
q.push(Node(u,v.order+1));
}
//down
u=v.value-e[v.value];
if(u>=1&&!book[u])
{
book[u]=1;
q.push(Node(u,v.order+1));
}
}
if(!book[b])
printf("-1\n");
return 0;
}
作者参加了一次算法实践课程的期末测验,通过三道题目的解答过程,反思了自己在算法学习上的不足之处,并分享了AC代码。
3184

被折叠的 条评论
为什么被折叠?



