标签:
第一题是A - FatMouse and Cheese,其实就是一个滑雪的类似题目,只能往奶酪多的地方走,但是可以跳跃的走,在上下左右k步范围内的都行,主要的想法就是DFS搜索,每一次的四个方向DFS搜索,找到它其中的最大值,然后记录下来,和当前点的值加起来,就是当前点最终能吃到的最多奶酪.
jud[i][j]=max(i=0~k,j=0~4)+mapp[i][j]
这种回溯的题目都只能用DFS,如果用BFS会导致大量的多余运算,很有可能超时.我wa了多次,就是因为写成了BFS
Description
Input
Output
Sample Input
Sample Output
1 #include<iostream> 2 #include<stdio.h> 3 #include<string.h> 4 #include<string> 5 #include<cmath> 6 #include<queue> 7 #include<algorithm> 8 using namespace std; 9 int mapp[105][105]={0},n,jud[105][105]={0},k; 10 int dfs(int x,int y) 11 { 12 int i,max1=0; 13 if(!jud[x][y]) 14 { 15 for(i=1;i<=k;i++) 16 { 17 if(x+i<=n&&x+i>0&&mapp[x][y]<mapp[x+i][y]) 18 { 19 jud[x+i][y]=dfs(x+i,y); 20 if(jud[x+i][y]>max1) 21 max1=jud[x+i][y]; 22 } 23 if(x-i>0&&x-i<=n&&mapp[x][y]<mapp[x-i][y]) 24 { 25 jud[x-i][y]=dfs(x-i,y); 26 if(jud[x-i][y]>max1) 27 max1=jud[x-i][y]; 28 } 29 if(y+i<=n&&y+i>0&&mapp[x][y]<mapp[x][y+i]) 30 { 31 jud[x][y+i]=dfs(x,y+i); 32 if(jud[x][y+i]>max1) 33 max1=jud[x][y+i]; 34 } 35 if(y-i>0&&y-i<=n&&mapp[x][y]<mapp[x][y-i]) 36 { 37 jud[x][y-i]=dfs(x,y-i); 38 if(jud[x][y-i]>max1) 39 max1=jud[x][y-i]; 40 } 41 } 42 jud[x][y]=max1+mapp[x][y]; 43 } 44 return jud[x][y]; 45 } 46 int main() 47 { 48 int i,j; 49 while(scanf("%d%d",&n,&k)&&(n!=-1||k!=-1)) 50 { 51 memset(jud,0,sizeof(jud)); 52 for(i=1;i<=n;i++) 53 for(j=1;j<=n;j++) 54 scanf("%d",&mapp[i][j]); 55 printf("%d\n",dfs(1,1)); 56 } 57 return 0; 58 }
第二题是Escape,也是一个迷宫,规则是遇到转弯口就必定要转弯,不能往回走,不能停留,问能否找到出口。这题是一个BFS题目,用DFS也一样能解,毕竟路径只有有限的,这题是记忆化BFS,需要记录的是进入一个点是否有从同一个方向进入,如果有那这个点就不能走。然后走到每个点的时候需要判定一下是不是转弯口,如果是转弯口就一定要转弯.
关键在于来时方向的记录,和判定转弯,可以用dx[4],dy[4]来表示方向,然后px,py表示来时方向,如果前方有路可以走,判定一下两边是否有路可以走,可以走的话就只能走两边。后来发现用0,1,2,3就可以表示四个方向,方向记录也只需要一个参数,然后(dir[k]+1)%4或者(dir[k]+3)%4来向两边转弯.
wa了多次的原因是因为,走到出口的判定我判了遇到出口就出,其实是就算遇到出口,也需要判一下是不是直走的,如果是正前方是出口但能转弯也是不能出的.
Description
Input
Output
Sample Input
Sample Output
1 #include<iostream> 2 #include<stdio.h> 3 #include<string.h> 4 #include<string> 5 #include<cmath> 6 #include<queue> 7 #include<algorithm> 8 using namespace std; 9 struct node 10 { 11 int xx; 12 int yy; 13 int pastx; 14 int pasty; 15 int num; 16 }; 17 char mapp[105][105]={‘\0‘}; 18 int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0}; 19 int sx,sy,h,w,n,mark=0; 20 int pastmapp[105][105][5][5]={0}; 21 int jud(int x,int y,int pastx,int pasty,int dx,int dy,int num) 22 { 23 int mark1=0,mark2=0; 24 if(pastx==0&&pasty==0) 25 { 26 if(mapp[x+dx][y+dy]==‘.‘) 27 return 1; 28 else 29 return 0; 30 }//第一个开始走 31 else 32 { 33 if(mapp[x+dx][y+dy]==‘\0‘)//到达终点没 34 {printf("%d\n",num);mark=1;return 1;} 35 if(x+dx>0&&x+dx<=h&&y+dy>0&&y+dy<=w&&mapp[x+dx][y+dy]==‘.‘) 36 { 37 if(pastx==0&&pasty==1)mark1=1; 38 else if(pastx==0&&pasty==-1)mark1=2; 39 else if(pastx==1&&pasty==0)mark1=3; 40 else mark1=4; 41 42 if(dx==0&&dy==1)mark2=1; 43 else if(dx==0&&dy==-1)mark2=2; 44 else if(dx==1&&dy==0)mark2=3; 45 else mark2=4; 46 47 if(pastmapp[x][y][mark1][mark2]) 48 return 0; 49 else 50 pastmapp[x][y][mark1][mark2]=1; 51 52 if(dx!=pastx||dy!=pasty) 53 return 1; 54 else 55 { 56 if((dx==0&&dy==1)||(dx==0&&dy==-1)) 57 { 58 if(mapp[x+1][y]==‘#‘&&mapp[x-1][y]==‘#‘) 59 return 1; 60 return 0; 61 } 62 else 63 { 64 if(mapp[x][y+1]==‘#‘&&mapp[x][y-1]==‘#‘) 65 return 1; 66 return 0; 67 } 68 } 69 } 70 else 71 return 0; 72 } 73 } 74 int jud2(int px,int py,int dx,int dy) 75 { 76 if(px==0&&py==0) 77 return 0; 78 if(px==0&&py==-1&&dx==0&&dy==1) 79 return 1; 80 else if(px==0&&py==1&&dx==0&&dy==-1) 81 return 1; 82 else if(px==1&&py==0&&dx==-1&&dy==0) 83 return 1; 84 else if(px==-1&&py==0&&dx==1&&dy==0) 85 return 1; 86 else 87 return 0; 88 } 89 void bfs(int x,int y) 90 { 91 int i,j; 92 node temp,temp2; 93 queue<node>q; 94 mark=0; 95 temp.xx=x; 96 temp.yy=y; 97 temp.pastx=0; 98 temp.pasty=0; 99 temp.num=0; 100 q.push(temp); 101 while(!q.empty()) 102 { 103 if(mark==1) 104 break; 105 temp=q.front(); 106 q.pop(); 107 for(i=0;i<4;i++) 108 { 109 if(jud2(temp.pastx,temp.pasty,dx[i],dy[i]))//判是不是往回走的方向 110 continue; 111 if(jud(temp.xx,temp.yy,temp.pastx,temp.pasty,dx[i],dy[i],temp.num)) 112 { 113 if(mark==1) 114 break; 115 temp2.xx=temp.xx+dx[i]; 116 temp2.yy=temp.yy+dy[i]; 117 temp2.pastx=dx[i]; 118 temp2.pasty=dy[i]; 119 temp2.num=temp.num+1; 120 q.push(temp2); 121 } 122 } 123 if(mark==1) 124 break; 125 } 126 if(mark==0) 127 printf("-1\n"); 128 } 129 int main() 130 { 131 int i,j,mark3=0; 132 scanf("%d",&n); 133 while(n--) 134 { 135 scanf("%d%d",&h,&w); 136 getchar(); 137 for(i=1;i<=h;i++) 138 { 139 for(j=1;j<=w;j++) 140 scanf("%c",&mapp[i][j]); 141 getchar(); 142 } 143 for(i=1;i<=h;i++) 144 for(j=1;j<=w;j++) 145 if(mapp[i][j]==‘@‘) 146 {sx=i;sy=j;break;} 147 //printf("%d%d",sx,sy); 148 mark3=0; 149 for(i=0;i<4;i++) 150 {if(mapp[sx+dx[i]][sy+dy[i]]==‘\0‘) 151 {printf("0\n");mark3=1;break;} 152 if(mark3) 153 break;} 154 if(mark3) 155 continue; 156 bfs(sx,sy); 157 for(i=1;i<=h;i++) 158 for(j=1;j<=w;j++) 159 for(int q=1;q<=4;q++) 160 for(int p=1;p<=4;p++) 161 pastmapp[i][j][p][q]=0; 162 memset(mapp,‘\0‘,sizeof(mapp)); 163 } 164 return 0; 165 }
第三题是strange left,也就是用最基本的BFS就能解的题目,不多说,只需要判重是否走过这一层就行了。
Description
Input
Output
Sample Input
Sample Output
1 #include<iostream> 2 #include<stdio.h> 3 #include<string.h> 4 #include<string> 5 #include<cmath> 6 #include<algorithm> 7 #include<queue> 8 using namespace std; 9 int line[205]; 10 int main() 11 { 12 int a,b,n,temp,tempnum,i,mark; 13 while(scanf("%d",&n)&&n!=0) 14 { 15 int marking[205]={0}; 16 queue<int>q,num; 17 mark=0; 18 scanf("%d%d",&a,&b); 19 for(i=1;i<=n;i++) 20 scanf("%d",&line[i]); 21 if(a==b) 22 {printf("0\n");continue;} 23 q.push(a); 24 num.push(0); 25 while(!q.empty()) 26 { 27 temp=q.front(); 28 tempnum=num.front(); 29 q.pop();num.pop(); 30 if((temp+line[temp]==b||temp-line[temp]==b)&&(temp+line[temp]<=n||temp-line[temp]>0)) 31 { 32 mark=1;printf("%d\n",tempnum+1);break; 33 } 34 if(temp+line[temp]<=n) 35 { 36 if(marking[temp+line[temp]]==0) 37 { 38 q.push(temp+line[temp]); 39 num.push(tempnum+1); 40 } 41 } 42 if(temp-line[temp]>0) 43 { 44 if(marking[temp-line[temp]]==0) 45 { 46 q.push(temp-line[temp]); 47 num.push(tempnum+1); 48 } 49 } 50 marking[temp]=1; 51 } 52 if(!mark) 53 printf("-1\n"); 54 } 55 return 0; 56 }
第四题是翻纸牌游戏,翻一个纸牌,会依次带动左右两张纸牌翻动,本意应该是要用数字来表示状态,然后用位运算BFS,但是其实用贪心的算法能0ms过,因为每个纸牌只有翻偶数次的结果是一样的,所以每个纸牌都只有翻与不翻的区别。从左往右依次递归。
需要注意的是,第一个纸牌仍然需要分类翻和不翻,可以做一个假想,比如在第一个纸牌的左边还有一张虚拟纸牌,因为虚拟纸牌的状态不定,所以导致第一张纸牌可能会翻和不翻,这个和他本身是什么颜色是没有关系的,因为第一张纸牌翻不翻与虚拟纸牌的颜色有关系。
Description
Input
Output
Sample Input
Sample Output
1 #include<iostream> 2 #include<stdio.h> 3 #include<string.h> 4 #include<string> 5 #include<cmath> 6 #include<queue> 7 #include<algorithm> 8 #define inf 100000 9 using namespace std; 10 char a[25],b[25]; 11 int main() 12 { 13 while(scanf("%s",a)!=EOF) 14 { 15 int i=0,j,t=strlen(a),time=0,mark=0,mark2=0,time2=0,temp1,add=0; 16 if(t==1) 17 { 18 if(a[t-1]==‘0‘) 19 printf("0\n"); 20 else 21 printf("1\n"); 22 continue; 23 } 24 for(i=0;i<t;i++) 25 b[i]=a[i]; 26 if(a[0]==‘1‘) 27 a[0]=‘0‘; 28 else 29 a[0]=‘1‘; 30 if(a[1]==‘1‘) 31 a[1]=‘0‘; 32 else 33 a[1]=‘1‘;//翻第一个 34 time++; 35 if(a[0]==‘1‘) 36 i=0; 37 else 38 i=1; 39 for(i;i<t;i++) 40 { 41 mark=0; 42 if(a[i]==‘1‘) 43 { 44 if(i+1<t) 45 { 46 mark=1; 47 if(a[i+1]==‘1‘) 48 a[i+1]=‘0‘; 49 else 50 a[i+1]=‘1‘; 51 } 52 if(i+2<t) 53 { 54 if(a[i+2]==‘1‘) 55 a[i+2]=‘0‘; 56 else 57 a[i+2]=‘1‘; 58 } 59 if(mark) 60 { 61 time++; 62 a[i]=‘0‘; 63 } 64 } 65 } 66 if(a[t-1]!=‘0‘||a[0]==‘1‘) 67 {time=inf;} 68 for(i=0;i<t;i++) 69 { 70 mark=0; 71 if(b[i]==‘1‘) 72 { 73 if(i+1<t) 74 { 75 mark=1; 76 if(b[i+1]==‘1‘) 77 b[i+1]=‘0‘; 78 else 79 b[i+1]=‘1‘; 80 } 81 if(i+2<t) 82 { 83 84 if(b[i+2]==‘1‘) 85 b[i+2]=‘0‘; 86 else 87 b[i+2]=‘1‘; 88 } 89 if(mark) 90 { 91 b[i]==‘0‘; 92 time2++; 93 } 94 } 95 } 96 if(b[t-1]!=‘0‘) 97 time2=inf; 98 if(time==inf&&time2==inf) 99 printf("NO\n"); 100 else 101 {printf("%d\n",time<time2?time:time2);} 102 } 103 return 0; 104 }
第五题是经典的搜索题,sticks,给定一些不同长度的棍子,搜索拼成一组相同长度的棍子的最小值.
整体思路就是先确定结果的范围,因为结果如果分一组,那就不必讨论,做个特判就好,如果要分组的话,至少分两组,所以min(len)<=ans<=sum/2
然后确定一个ans后,进入DFS,枚举状态,这里需要大量的剪枝有六个剪枝。
1.相同长度的棍子,当前这根没被选上,那么直接跳到下一根长度不同的开始。
2.如果该棍子是拼接组合的第一根,如果不成功则说明上一组的棍子拼接有问题,不需要继续递归找,直接回溯上一根。
基本最强力的简直就是这两个,还有一些就是简单的判重,长度超了不能放进来,被用过的不能放进来.
注意!递归如果已经完成一根,那么pos位置要回到第一根开始重新找,而不是在当前这个位置继续,因为前面还有可能没组合上的,当然首先要排序。
Description
Input
Output
Sample Input
Sample Output
1 #include<iostream> 2 #include<stdio.h> 3 #include<string> 4 #include<string.h> 5 #include<cmath> 6 #include<queue> 7 #include<stack> 8 #include<algorithm> 9 using namespace std; 10 int len[100]={0},n,vis[100]={0},ans,requirenum; 11 bool cmp(int a,int b) 12 { 13 return a>b; 14 } 15 bool dfs(int pos,int sum,int num) 16 { 17 if(num==requirenum)///走到终点 18 { 19 return true; 20 } 21 for(int i=pos;i<n;i++) 22 if(!vis[i]&&(sum+len[i])<=ans)///没用过这一根,而且长度小于等于目标长度 23 { 24 //if(i==0||(i>=1&&len[i-1]==len[i]&&vis[i-1])||(len[i-1]!=len[i]))///上一根和它相同长度的要被用过 25 //{ 26 if((sum+len[i])==ans) 27 { 28 vis[i]=1; 29 if(dfs(0,0,num+1))///完成一根棍子回到0位 30 return true; 31 vis[i]=0; 32 return false;///说明当前这根已经完成棍子组合不行,不是这么组合的 33 } 34 else 35 { 36 vis[i]=1; 37 if(dfs(i+1,sum+len[i],num)) 38 return true; 39 vis[i]=0; 40 if(!sum) 41 return false;///如果这根是放入组合的第一根,并且不能完成,那么说明上一个组合有问题,回溯 42 43 while(len[i]==len[i+1])///当前这根不行,那么下面相同长度的几根也都不行,直接跳到不同的开始 44 i++; 45 } 46 //} 47 } 48 return false; 49 } 50 int main() 51 { 52 int t,num,i,j,sum,mark; 53 while(scanf("%d",&n)&&n!=0) 54 { 55 sum=0;mark=0; 56 for(i=0;i<n;i++) 57 {scanf("%d",&len[i]);sum+=len[i];} 58 sort(len,len+n,cmp); 59 for(ans=len[n-1];ans<=sum/2;ans++) 60 { 61 if(!(sum%ans))///能整除 62 { 63 requirenum=sum/ans;///一共需要多少根一样的棒子 64 memset(vis,0,sizeof(vis)); 65 if(dfs(0,0,0))///从0位置开始,当前凑的长度为0,现在凑齐了0根 66 {printf("%d\n",ans);mark=1;break;} 67 } 68 } 69 if(!mark) 70 printf("%d\n",sum); 71 memset(len,0,sizeof(len)); 72 } 73 return 0; 74 }
标签:
原文地址:http://www.cnblogs.com/linminxuan/p/4682098.html