暑期集训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

Description

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 of

a 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 -1
 

Sample 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

Description

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

Description

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 0
 

Sample 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

Description

有一种纸牌游戏,很有意思,给你N张纸牌,一字排开,纸牌有正反两面,开始的纸牌可能是一种乱的状态(有些朝正,有些朝反),现在你需要整理这些纸牌。但 是麻烦的是,每当你翻一张纸牌(由正翻到反,或者有反翻到正)时,他左右两张纸牌(最左边和最右边的纸牌,只会影响附近一张)也必须跟着翻动,现在给你一 个乱的状态,问你能否把他们整理好,使得每张纸牌都正面朝上,如果可以,最少需要多少次操作。
 

Input

有多个case,每个case输入一行01符号串(长度不超过20),1表示反面朝上,0表示正面朝上。
 

Output

对于每组case,如果可以翻,输出最少需要翻动的次数,否则输出NO。
 

Sample Input

01 011
 

Sample 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

Description

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 0
 

Sample 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 }

 

posted @ 2015-07-28 10:33  kingofprank  阅读(294)  评论(0编辑  收藏  举报