第一次不是以学为目的的做题,之前的题都是看了基本算法和模板代码以后去做的,所以这次非常有挑战性, 当然,这种难度还是轻松把我打败了
A是hdu3088 WORM ,一道hash判重+BFS,一开始不会hash判重,更别说三进制hash了,那天正好看了lrj的书,里面一道八数码跟这题差不多,于是就硬写了两个钟头,到头来才发现memcmp和strcmp的原理不一样,用法也不一样,如果两个数组的开头a[0],b[0]是一样的,那么memcmp就会判断它是一样的,因为八数码问题每个数都不相同,所以lrj才那么用,算是被他坑了。后来因为没有懂得把r,b,g换成数字,也着实麻烦了一阵。
//hash三进制判重+BFS //输入rgb字符串转化成字符的123 //自己写的再看别人的代码以后才ac #include#include #include #include using namespace std;const int maxst=100000;//字母的状态有3^10种排列 int t,len,h;bool vis[maxst];//hash表 int goal[3];char str[11];struct state{ char ch[11]; int step;};//队列节点 char change(char a,char b){ if(a+b == '0'+'1') return '2'; if(a+b == '0'+'2') return '1'; if(a+b == '1'+'2') return '0';}int Hash(char* a){ int s=0,x; for(int i=0;i q; int step; state u; memset(vis,0,sizeof(vis)); h=Hash(str);//习惯性的要先处理第一组数据 if(h==goal[0]||h==goal[1]||h==goal[2]) return 0; strcpy(u.ch,str); u.step=0; q.push(u); vis[h]=1; while(!q.empty()){ u=q.front(); u.step++; q.pop(); h=Hash(u.ch); for(int i=0;i >t; while(t--) { cin>>str; getchar(); len=strlen(str); for(int i=0;i
B是hdu3091 Necklace,一道状态DP,本身比较简单,但是题目意思含糊,题目是说找出项链的方案,但貌似项链可以不用形成环。。。。所以这题我也无耻的看了别人的代码,其实最重要的原因是我根本没写过状态压缩T0T
/* 找出n个珠子的某种组合方式,将这些组合方式放在一个二进制数里面 对每一个二进制状态S进行列举dp表示能够形成的条数,i表示链条的终点, dp[S+{j}][j]=sigma dp[S][i] //i-j存在边,且i在S内 *///无向图#include#include #include using namespace std;long long dp[(1<<18)+5][20];//开到19太大了 //注意< <时要用括号 注意数据要用long long储存 int a,b,n,m;int maxs,s2,p;int s,i,j;int main(){ while(cin> >n>>m) { vector v[20];//邻接表 memset(dp,0,sizeof(dp)); for(i=0;i >a>>b; a--;b--; v[a].push_back(b); v[b].push_back(a);//注意减1!!! } //S=1<<0代表空集,空集时显然不存在S之外某个点的邻接顶点在S中 dp[1][0]=1; maxS=1< 时要用括号>
C是双向BFS,我到现在还是不会。。。
D是hdu1254 推箱子,是一道比较明显的BFS+DFS或BFS+BFS,一开始写前一种不知道到底错在那里,后来把DFS换成BFS就AC了,这题写了一晚上还有早上两钟头。。。
//显然当仅当箱子左右都是空地且不是边界时且人可到达时,人可以站在箱子左右推,既可往左推,也可往右推,并且箱子将被推到右边一格,步数加1,而此时人一定在箱子的左边 //遍历箱子的四个方向中可推的,然后推入队列。同时要带上人的位置//判断人能否到达一个位置//如果这个位置是边界或者墙,则不行//如果不是,则dfs //mbd第一次写TLE,第二次什么都没改就0ms AC了 #include#include #include using namespace std;int t,n,m,endx,endy;const int dir[4][2]={ {-1,0},{ 1,0},{ 0,1},{ 0,-1}};//左右上下 int map[8][8];bool vis[8][8][8][8];//用四维数组储存状态, bool mark[8][8];bool can_stand(int x,int y){ //处于状态u的时候的地图 if(x<=n&&x>0&&y>0&&y<=m&&map[x][y]!=1&&map[x][y]!=2)//先判断边界在判断map 注意map为3时也是可以走的 return 1; return 0;}struct state{ int cx,cy;//此时人的位置 int bx,by;//此时箱子的位置 int step; state(){} state(int a,int b,int c,int d,int s){ cx=a;cy=b;bx=c;by=d;step=s; }}; struct node{ int x,y;//差点多打了个变量step };bool bfs2(state u,int x,int y){ //只需要判断能否到达 memset(mark,0,sizeof(mark)); queue q; node t,k; t.x=u.cx; t.y=u.cy; mark[t.x][t.y]=1; q.push(t); while(!q.empty()){ k=q.front(); q.pop(); if(k.x==x&&k.y==y) return 1; for(int i=0;i<4;i++) { int nx=k.x+dir[i][0],ny=k.y+dir[i][1]; if(can_stand(nx,ny)&&!mark[nx][ny]) { t.x=nx;t.y=ny; q.push(t); mark[nx][ny]=1; } } } return 0;}int bfs(){ //走到一个位置时,要记得改变map的值 queue q; state u; memset(vis,0,sizeof(vis)); for(int i=1;i<=m;i++){ for(int j=1;j<=n;j++) { if(map[j][i]==2) { u.bx=j;u.by=i; } if(map[j][i]==3) { endx=j;endy=i; } if(map[j][i]==4) { u.cx=j;u.cy=i; } } } u.step=0; q.push(u); int nx,ny,rx,ry; while(!q.empty()){ u=q.front(); q.pop(); if(u.bx==endx&&u.by==endy) return u.step; vis[u.cx][u.cy][u.bx][u.by]=1; map[u.bx][u.by]=2;//在此之前地图中没有箱子 for(int i=0;i<4;i++) { nx=u.bx+dir[i][0];ny=u.by+dir[i][1];//推箱子的时候人应该站的位置 rx=u.bx-dir[i][0];ry=u.by-dir[i][1];//箱子要被推到的位置 if(can_stand(nx,ny)&&can_stand(rx,ry)&&!vis[nx][ny][rx][ry]) if(bfs2(u,nx,ny))//u这个状态的人能不能到达(nx,ny) { state v(u.bx,u.by,rx,ry,u.step+1); q.push(v); vis[nx][ny][rx][ry]=1; } } //判断箱子周围可到达的格子之后 map[u.bx][u.by]=0; } return -1;}int main(){ cin>>t; while(t--) { memset(map,0,sizeof(map)); cin>>m>>n;//m行n列 map[j][i] j列i行 for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) cin>>map[j][i]; cout< <
E是hdu1284 钱币兑换问题,一道数学水题,没啥意思
//决定了y与z之后,x就被唯一决定了 #includeusing namespace std;int n,sum;int main(){ while(cin>>n) { sum=0; for(int i=0;i<=n/3;i++) sum+=(n-3*i)/2+1; cout< <
F是hdu1285 确定比赛名次,一道拓扑排序,本来很简单,但是我之前没写过拓扑,不过看了思路以后就一次AC了
//hdu1285 方法想不到 #include#include #include using namespace std;const int maxn=505;int n, m;int d[maxn]; bool vis[maxn];int main() { int i, j; while (cin>>n>>m) { vector v[maxn]; memset(d,0,sizeof(d)); for (int i=1;i<=m;i++) { int a, b; cin>>a>>b; d[b]++; v[a].push_back(b); } memset(vis,0,sizeof(vis)); int c=0;//已经输出了几个 for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++)//因为要按字典序输出,所以从前往后找点 if(!vis[j]&&!d[j]) { vis[j]=1; for(int k=0;k