暑期集训1DAY
第一題是A - FatMouse and Cheese,其實就是一個滑雪的類似題目,只能往奶酪多的地方走,但是可以跳躍的走,在上下左右k步范圍內的都行,主要的想法就是DFS搜索,每一次的四個方向DFS搜索,找到它其中的最大值,然后記錄下來,和當前點的值加起來,就是當前點最終能吃到的最多奶酪.
jud[i][j]=max(i=0~k,j=0~4)+mapp[i][j]
這種回溯的題目都只能用DFS,如果用BFS會導致大量的多余運算,很有可能超時.我wa了多次,就是因為寫成了BFS
A - FatMouse and Cheese Time Limit:1000MS???? Memory Limit:32768KB???? 64bit IO Format:%I64d & %I64u Submit Status Practice HDU 1078Description
FatMouse has stored some cheese in a city. The city can be considered as a square grid of dimension n: each grid location is labelled (p,q) where 0 <= p < n and 0 <= q < n. At each grid location Fatmouse has hid between 0 and 100 blocks of cheese in a hole. Now he's going to enjoy his favorite food.FatMouse begins by standing at location (0,0). He eats up the cheese where he stands and then runs either horizontally or vertically to another location. The problem is that there is a super Cat named Top Killer sitting near his hole, so each time he can run at most k locations to get into the hole before being caught by Top Killer. What is worse -- after eating up the cheese at one location, FatMouse gets fatter. So in order to gain enough energy for his next run, he has to run to a location which have more blocks of cheese than those that were at the current hole.
Given n, k, and the number of blocks of cheese at each grid location, compute the maximum amount of cheese FatMouse can eat before being unable to move.
Input
There are several test cases. Each test case consists ofa line containing two integers between 1 and 100: n and k
n lines, each with n numbers: the first line contains the number of blocks of cheese at locations (0,0) (0,1) ... (0,n-1); the next line contains the number of blocks of cheese at locations (1,0), (1,1), ... (1,n-1), and so on.
The input ends with a pair of -1's.
Output
For each test case output in a line the single integer giving the number of blocks of cheese collected.Sample Input
3 1 1 2 5 10 11 6 12 12 7 -1 -1Sample Output
37 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了多次的原因是因為,走到出口的判定我判了遇到出口就出,其實是就算遇到出口,也需要判一下是不是直走的,如果是正前方是出口但能轉彎也是不能出的.
?
B - Escape Time Limit:1000MS???? Memory Limit:32768KB???? 64bit IO Format:%I64d & %I64u Submit Status Practice HDU 2364Description
You find yourself trapped in a large rectangular room, made up of large square tiles; some are accessible, others are blocked by obstacles or walls. With a single step, you can move from one tile to another tile if it is horizontally or vertically adjacent (i.e. you cannot move diagonally).To shake off any people following you, you do not want to move in a straight line. In fact, you want to take a turn at every opportunity, never moving in any single direction longer than strictly necessary. This means that if, for example, you enter a tile from the south, you will turn either left or right, leaving to the west or the east. Only if both directions are blocked, will you move on straight ahead. You never turn around and go back!
Given a map of the room and your starting location, figure out how long it will take you to escape (that is: reach the edge of the room).
Input
On the first line an integer t (1 <= t <= 100): the number of test cases. Then for each test case:a line with two integers separated by a space, h and w (1 <= h, w <= 80), the height and width of the room;
then h lines, each containing w characters, describing the room. Each character is one of . (period; an accessible space), # (a blocked space) or @ (your starting location).
There will be exactly one @ character in each room description.
Output
For each test case:A line with an integer: the minimal number of steps necessary to reach the edge of the room, or -1 if no escape is possible.
Sample Input
2 9 13 ############# #@..........# #####.#.#.#.# #...........# #.#.#.#.#.#.# #.#.......#.# #.#.#.#.#.#.# #...........# #####.####### 4 6 #.#### #.#.## #...@# ######Sample Output
31 -1 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就能解的題目,不多說,只需要判重是否走過這一層就行了。
C - A strange lift Time Limit:1000MS???? Memory Limit:32768KB???? 64bit IO Format:%I64d & %I64u Submit Status Practice HDU 1548Description
There is a strange lift.The lift can stop can at every floor as you want, and there is a number Ki(0 <= Ki <= N) on every floor.The lift have just two buttons: up and down.When you at floor i,if you press the button "UP" , you will go up Ki floor,i.e,you will go to the i+Ki th floor,as the same, if you press the button "DOWN" , you will go down Ki floor,i.e,you will go to the i-Ki th floor. Of course, the lift can't go up high than N,and can't go down lower than 1. For example, there is a buliding with 5 floors, and k1 = 3, k2 = 3,k3 = 1,k4 = 2, k5 = 5.Begining from the 1 st floor,you can press the button "UP", and you'll go up to the 4 th floor,and if you press the button "DOWN", the lift can't do it, because it can't go down to the -2 th floor,as you know ,the -2 th floor isn't exist.Here comes the problem: when you are on floor A,and you want to go to floor B,how many times at least he has to press the button "UP" or "DOWN"?
Input
The input consists of several test cases.,Each test case contains two lines.The first line contains three integers N ,A,B( 1 <= N,A,B <= 200) which describe above,The second line consist N integers k1,k2,....kn.
A single 0 indicate the end of the input.
Output
For each case of the input output a interger, the least times you have to press the button when you on floor A,and you want to go to floor B.If you can't reach floor B,printf "-1".Sample Input
5 1 5 3 3 1 2 5 0Sample Output
3 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過,因為每個紙牌只有翻偶數次的結果是一樣的,所以每個紙牌都只有翻與不翻的區別。從左往右依次遞歸。
需要注意的是,第一個紙牌仍然需要分類翻和不翻,可以做一個假想,比如在第一個紙牌的左邊還有一張虛擬紙牌,因為虛擬紙牌的狀態不定,所以導致第一張紙牌可能會翻和不翻,這個和他本身是什么顏色是沒有關系的,因為第一張紙牌翻不翻與虛擬紙牌的顏色有關系。
D - 翻紙牌游戲 Time Limit:3000MS???? Memory Limit:32768KB???? 64bit IO Format:%I64d & %I64u Submit Status Practice HDU 2209
Description
有一種紙牌游戲,很有意思,給你N張紙牌,一字排開,紙牌有正反兩面,開始的紙牌可能是一種亂的狀態(有些朝正,有些朝反),現在你需要整理這些紙牌。但 是麻煩的是,每當你翻一張紙牌(由正翻到反,或者有反翻到正)時,他左右兩張紙牌(最左邊和最右邊的紙牌,只會影響附近一張)也必須跟著翻動,現在給你一 個亂的狀態,問你能否把他們整理好,使得每張紙牌都正面朝上,如果可以,最少需要多少次操作。Input
有多個case,每個case輸入一行01符號串(長度不超過20),1表示反面朝上,0表示正面朝上。Output
對于每組case,如果可以翻,輸出最少需要翻動的次數,否則輸出NO。Sample Input
01 011Sample Output
NO 1 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位置要回到第一根開始重新找,而不是在當前這個位置繼續,因為前面還有可能沒組合上的,當然首先要排序。
E - Sticks Time Limit:1000MS???? Memory Limit:32768KB???? 64bit IO Format:%I64d & %I64u Submit Status Practice HDU 1455Description
George took sticks of the same length and cut them randomly until all parts became at most 50 units long. Now he wants to return sticks to the original state, but he forgot how many sticks he had originally and how long they were originally. Please help him and design a program which computes the smallest possible original length of those sticks. All lengths expressed in units are integers greater than zero.Input
The input contains blocks of 2 lines. The first line contains the number of sticks parts after cutting, there are at most 64 sticks. The second line contains the lengths of those parts separated by the space. The last line of the file contains zero.Output
The output file contains the smallest possible length of original sticks, one per line.Sample Input
9 5 2 1 5 2 1 5 2 1 4 1 2 3 4 0Sample Output
6 5 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 }?
轉載于:https://www.cnblogs.com/linminxuan/p/4682098.html
總結
- 上一篇: [android] AndroidMan
- 下一篇: git 修改上次提交信息 与 撤销此操