The 2014 ACMICPC Asia Regional Guangzhou Online
【A】-_-///
【B】线段树+位运算(感觉可出)
【E】-_-///
【F】三分+圆与线段的交点,计算几何
【G】-_-///
【H】线段树+树链剖分
【I】后缀数组+二分
【J】DFS搜索
这场网赛当时自己完成了的也就是两道地图题,过去好久了才想到还是该记录下来...
Wang Xifeng's Little Plot
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
In the novel, Wang Xifeng was in charge of Da Guan Yuan, where people of Jia family lived. It was mentioned in the newly recovered pages that Wang Xifeng used to arrange rooms for Jia Baoyu, Lin Daiyu, Xue Baochai and other teenagers. Because Jia Baoyu was the most important inheritor of Jia family, and Xue Baochai was beautiful and very capable , Wang Xifeng didn't want Jia Baoyu to marry Xue Baochai, in case that Xue Baochai might take her place. So, Wang Xifeng wanted Baoyu's room and Baochai's room to be located at two ends of a road, and this road should be as long as possible. But Baoyu was very bad at directions, and he demanded that there could be at most one turn along the road from his room to Baochai's room, and if there was a turn, that turn must be ninety degree. There is a map of Da Guan Yuan in the novel, and redists (In China English, one whose job is studying 《Dream of the Red Chamber》is call a "redist") are always arguing about the location of Baoyu's room and Baochai's room. Now you can solve this big problem and then become a great redist.
There are several test cases.
For each case, the first line is an integer N(0<N<=100) ,meaning the map is a N × N matrix.
Then the N × N matrix follows.
The input ends with N = 0.
3 #.# ##. ..# 3 ... ##. ..# 3 ... ### ..# 3 ... ##. ... 0
【Sample Output】
3 4 3 5
【题意】
给出一张图,'.'表示路,'#'表示墙,要求找出一条最长的路,路径上只允许转弯一次。
【分析】
本题首先应该看到虽然要求是可以向八个方向走,但是由于转弯只能是90°的直角弯,所以上下左右四个方向与另外四个方向是完全独立的。
所以直观的想法是分成两组进行BFS,从起点开始(起点应该为某一条路的尽头),记录下上一个点到达当前点的方向、是否转过弯,每一次向下一个点搜索的方向只有三个,记录沿途的最长距离即可。
这道题的代码写得太朴素了,方向这里写了一次复制了7遍,,,都不好意思贴出来了,,,-_-///
1 /* *********************************************** 2 MYID : Chen Fan 3 LANG : G++ 4 PROG : C1003 5 ************************************************ */ 6 7 #include <iostream> 8 #include <cstdio> 9 #include <cstring> 10 #include <algorithm> 11 12 using namespace std; 13 14 int dx1[4]={-1,1,1,-1}; 15 int dy1[4]={-1,-1,1,1}; 16 int dx2[4]={-1,0,1,0}; 17 int dy2[4]={0,-1,0,1}; 18 int ans; 19 bool ma[110][110]; 20 int num[110][110]; 21 22 bool check(int xx,int yy) 23 { 24 int temp1=0,temp2=0; 25 for (int i=0;i<4;i++) 26 { 27 temp1+=ma[xx+dx1[i]][yy+dy1[i]]; 28 temp2+=ma[xx+dx2[i]][yy+dy2[i]]; 29 } 30 if (temp1>0||temp2>0) return true; 31 else return false; 32 } 33 34 typedef struct nod{ 35 int x,y,fx; 36 bool zw; 37 } node; 38 node q[10010]; 39 40 void doit(int xx,int yy) 41 { 42 int head=1,tail=1; 43 memset(num,0,sizeof(num)); 44 q[head].x=xx; 45 q[head].y=yy; 46 q[head].fx=-1; 47 q[head].zw=false; 48 num[xx][yy]=1; 49 while (head<=tail) 50 { 51 if (ma[q[head].x-1][q[head].y-1]&&num[q[head].x-1][q[head].y-1]==0&&(q[head].fx==-1||q[head].fx==0||q[head].fx==1||q[head].fx==2)) 52 { 53 tail++; 54 q[tail].x=q[head].x-1; 55 q[tail].y=q[head].y-1; 56 if (q[head].fx==0||q[head].fx==-1) 57 { 58 q[tail].fx=0; 59 q[tail].zw=q[head].zw; 60 num[q[tail].x][q[tail].y]=num[q[head].x][q[head].y]+1; 61 if (ans<num[q[tail].x][q[tail].y]) ans=num[q[tail].x][q[tail].y]; 62 } else 63 if (q[head].zw==false) 64 { 65 q[tail].fx=0; 66 q[tail].zw=true; 67 num[q[tail].x][q[tail].y]=num[q[head].x][q[head].y]+1; 68 if (ans<num[q[tail].x][q[tail].y]) ans=num[q[tail].x][q[tail].y]; 69 } else tail--; 70 } 71 if (ma[q[head].x-1][q[head].y+1]&&num[q[head].x-1][q[head].y+1]==0&&(q[head].fx==-1||q[head].fx==0||q[head].fx==1||q[head].fx==3)) 72 { 73 tail++; 74 q[tail].x=q[head].x-1; 75 q[tail].y=q[head].y+1; 76 if (q[head].fx==1||q[head].fx==-1) 77 { 78 q[tail].fx=1; 79 q[tail].zw=q[head].zw; 80 num[q[tail].x][q[tail].y]=num[q[head].x][q[head].y]+1; 81 if (ans<num[q[tail].x][q[tail].y]) ans=num[q[tail].x][q[tail].y]; 82 } else 83 if (q[head].zw==false) 84 { 85 q[tail].fx=1; 86 q[tail].zw=true; 87 num[q[tail].x][q[tail].y]=num[q[head].x][q[head].y]+1; 88 if (ans<num[q[tail].x][q[tail].y]) ans=num[q[tail].x][q[tail].y]; 89 } else tail--; 90 } 91 if (ma[q[head].x+1][q[head].y-1]&&num[q[head].x+1][q[head].y-1]==0&&(q[head].fx==-1||q[head].fx==0||q[head].fx==2||q[head].fx==3)) 92 { 93 tail++; 94 q[tail].x=q[head].x+1; 95 q[tail].y=q[head].y-1; 96 if (q[head].fx==2||q[head].fx==-1) 97 { 98 q[tail].fx=2; 99 q[tail].zw=q[head].zw; 100 num[q[tail].x][q[tail].y]=num[q[head].x][q[head].y]+1; 101 if (ans<num[q[tail].x][q[tail].y]) ans=num[q[tail].x][q[tail].y]; 102 } else 103 if (q[head].zw==false) 104 { 105 q[tail].fx=2; 106 q[tail].zw=true; 107 num[q[tail].x][q[tail].y]=num[q[head].x][q[head].y]+1; 108 if (ans<num[q[tail].x][q[tail].y]) ans=num[q[tail].x][q[tail].y]; 109 } else tail--; 110 111 } 112 if (ma[q[head].x+1][q[head].y+1]&&num[q[head].x+1][q[head].y+1]==0&&(q[head].fx==-1||q[head].fx==1||q[head].fx==2||q[head].fx==3)) 113 { 114 tail++; 115 q[tail].x=q[head].x+1; 116 q[tail].y=q[head].y+1; 117 if (q[head].fx==3||q[head].fx==-1) 118 { 119 q[tail].fx=3; 120 q[tail].zw=q[head].zw; 121 num[q[tail].x][q[tail].y]=num[q[head].x][q[head].y]+1; 122 if (ans<num[q[tail].x][q[tail].y]) ans=num[q[tail].x][q[tail].y]; 123 } else 124 if (q[head].zw==false) 125 { 126 q[tail].fx=3; 127 q[tail].zw=true; 128 num[q[tail].x][q[tail].y]=num[q[head].x][q[head].y]+1; 129 if (ans<num[q[tail].x][q[tail].y]) ans=num[q[tail].x][q[tail].y]; 130 } else tail--; 131 } 132 head++; 133 } 134 135 head=1;tail=1; 136 memset(num,0,sizeof(num)); 137 num[xx][yy]=1; 138 while (head<=tail) 139 { 140 if (ma[q[head].x-1][q[head].y]&&num[q[head].x-1][q[head].y]==0&&(q[head].fx==-1||q[head].fx==0||q[head].fx==1||q[head].fx==2)) 141 { 142 tail++; 143 q[tail].x=q[head].x-1; 144 q[tail].y=q[head].y; 145 if (q[head].fx==0||q[head].fx==-1) 146 { 147 q[tail].fx=0; 148 q[tail].zw=q[head].zw; 149 num[q[tail].x][q[tail].y]=num[q[head].x][q[head].y]+1; 150 if (ans<num[q[tail].x][q[tail].y]) ans=num[q[tail].x][q[tail].y]; 151 } else 152 if (q[head].zw==false) 153 { 154 q[tail].fx=0; 155 q[tail].zw=true; 156 num[q[tail].x][q[tail].y]=num[q[head].x][q[head].y]+1; 157 if (ans<num[q[tail].x][q[tail].y]) ans=num[q[tail].x][q[tail].y]; 158 } else tail--; 159 } 160 if (ma[q[head].x][q[head].y-1]&&num[q[head].x][q[head].y-1]==0&&(q[head].fx==-1||q[head].fx==0||q[head].fx==1||q[head].fx==3)) 161 { 162 tail++; 163 q[tail].x=q[head].x; 164 q[tail].y=q[head].y-1; 165 if (q[head].fx==1||q[head].fx==-1) 166 { 167 q[tail].fx=1; 168 q[tail].zw=q[head].zw; 169 num[q[tail].x][q[tail].y]=num[q[head].x][q[head].y]+1; 170 if (ans<num[q[tail].x][q[tail].y]) ans=num[q[tail].x][q[tail].y]; 171 } else 172 if (q[head].zw==false) 173 { 174 q[tail].fx=1; 175 q[tail].zw=true; 176 num[q[tail].x][q[tail].y]=num[q[head].x][q[head].y]+1; 177 if (ans<num[q[tail].x][q[tail].y]) ans=num[q[tail].x][q[tail].y]; 178 } else tail--; 179 } 180 if (ma[q[head].x][q[head].y+1]&&num[q[head].x][q[head].y+1]==0&&(q[head].fx==-1||q[head].fx==0||q[head].fx==2||q[head].fx==3)) 181 { 182 tail++; 183 q[tail].x=q[head].x; 184 q[tail].y=q[head].y+1; 185 if (q[head].fx==2||q[head].fx==-1) 186 { 187 q[tail].fx=2; 188 q[tail].zw=q[head].zw; 189 num[q[tail].x][q[tail].y]=num[q[head].x][q[head].y]+1; 190 if (ans<num[q[tail].x][q[tail].y]) ans=num[q[tail].x][q[tail].y]; 191 } else 192 if (q[head].zw==false) 193 { 194 q[tail].fx=2; 195 q[tail].zw=true; 196 num[q[tail].x][q[tail].y]=num[q[head].x][q[head].y]+1; 197 if (ans<num[q[tail].x][q[tail].y]) ans=num[q[tail].x][q[tail].y]; 198 } else tail--; 199 200 } 201 if (ma[q[head].x+1][q[head].y]&&num[q[head].x+1][q[head].y]==0&&(q[head].fx==-1||q[head].fx==1||q[head].fx==2||q[head].fx==3)) 202 { 203 tail++; 204 q[tail].x=q[head].x+1; 205 q[tail].y=q[head].y; 206 if (q[head].fx==3||q[head].fx==-1) 207 { 208 q[tail].fx=3; 209 q[tail].zw=q[head].zw; 210 num[q[tail].x][q[tail].y]=num[q[head].x][q[head].y]+1; 211 if (ans<num[q[tail].x][q[tail].y]) ans=num[q[tail].x][q[tail].y]; 212 } else 213 if (q[head].zw==false) 214 { 215 q[tail].fx=3; 216 q[tail].zw=true; 217 num[q[tail].x][q[tail].y]=num[q[head].x][q[head].y]+1; 218 if (ans<num[q[tail].x][q[tail].y]) ans=num[q[tail].x][q[tail].y]; 219 } else tail--; 220 } 221 head++; 222 } 223 } 224 225 int main() 226 { 227 //freopen("C1003.txt","r",stdin); 228 229 int n; 230 scanf("%d",&n); 231 while (n) 232 { 233 getchar(); 234 memset(ma,0,sizeof(ma)); 235 for (int i=1;i<=n;i++) 236 { 237 for (int j=1;j<=n;j++) 238 { 239 char c; 240 scanf("%c",&c); 241 if (c=='.') ma[i][j]=true; 242 } 243 getchar(); 244 } 245 246 ans=0; 247 for (int i=1;i<=n;i++) 248 for (int j=1;j<=n;j++) 249 if (ma[i][j]&&check(i,j)) doit(i,j); 250 251 printf("%d\n",ans); 252 scanf("%d",&n); 253 } 254 255 return 0; 256 }
【启发】
对于这种初看8个方向,然后相互没有关系的一定注意分开考虑。
Saving Tang Monk
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
During the journey, Tang Monk was often captured by demons. Most of demons wanted to eat Tang Monk to achieve immortality, but some female demons just wanted to marry him because he was handsome. So, fighting demons and saving Monk Tang is the major job for Sun Wukong to do.
Once, Tang Monk was captured by the demon White Bones. White Bones lived in a palace and she cuffed Tang Monk in a room. Sun Wukong managed to get into the palace. But to rescue Tang Monk, Sun Wukong might need to get some keys and kill some snakes in his way.
The palace can be described as a matrix of characters. Each character stands for a room. In the matrix, 'K' represents the original position of Sun Wukong, 'T' represents the location of Tang Monk and 'S' stands for a room with a snake in it. Please note that there are only one 'K' and one 'T', and at most five snakes in the palace. And, '.' means a clear room as well '#' means a deadly room which Sun Wukong couldn't get in.
There may be some keys of different kinds scattered in the rooms, but there is at most one key in one room. There are at most 9 kinds of keys. A room with a key in it is represented by a digit(from '1' to '9'). For example, '1' means a room with a first kind key, '2' means a room with a second kind key, '3' means a room with a third kind key... etc. To save Tang Monk, Sun Wukong must get ALL kinds of keys(in other words, at least one key for each kind).
For each step, Sun Wukong could move to the adjacent rooms(except deadly rooms) in 4 directions(north, west, south and east), and each step took him one minute. If he entered a room in which a living snake stayed, he must kill the snake. Killing a snake also took one minute. If Sun Wukong entered a room where there is a key of kind N, Sun would get that key if and only if he had already got keys of kind 1,kind 2 ... and kind N-1. In other words, Sun Wukong must get a key of kind N before he could get a key of kind N+1 (N>=1). If Sun Wukong got all keys he needed and entered the room in which Tang Monk was cuffed, the rescue mission is completed. If Sun Wukong didn't get enough keys, he still could pass through Tang Monk's room. Since Sun Wukong was a impatient monkey, he wanted to save Tang Monk as quickly as possible. Please figure out the minimum time Sun Wukong needed to rescue Tang Monk.
For each case, the first line includes two integers N and M(0 < N <= 100, 0<=M<=9), meaning that the palace is a N×N matrix and Sun Wukong needed M kinds of keys(kind 1, kind 2, ... kind M).
Then the N × N matrix follows.
The input ends with N = 0 and M = 0.
3 1 K.S ##1 1#T 3 1 K#T .S# 1#. 3 2 K#T .S. 21. 0 0
【Sample Output】
5 impossible 8
【题意】
又是一道地图题,题目要求为从起点(悟空的位置)出发,按顺序通过m个点,最后到达终点(唐僧的位置),最后输出impossible或者全程的最短距离。
【分析】
当时看到题目就傻了好久,需要处理的问题太多:
1.钥匙可能有多把,即地图上好多个1,好多个2......
2.蛇的问题,刚开始看的时候还没觉得什么,以为标记一下经过的时候时间+1即可,后来发现有点不对,看了比赛时其他人的提问才知道原来我觉得不对的地方是真不对,有蛇的点经过一次之后蛇就会被杀死!!下次再经过就成了普通点!!
首先解决第一个问题,BFS搜距离+DFS选择路径:
这张图的大小最大只有100*100,总点数最大是10000,考虑最坏情况,即图中的所有点中都有钥匙,9种钥匙均匀分布大约是(9998/9=1110),然后1000^9是......///-_-///......妈蛋,当时没考虑这么多,现在想想如果真的碰到这么大的数据量,我这么做真是早就爆了......
我把所有钥匙相同的点都编为1组,然后用BFS搜出相邻两组所有点对之间的距离,最后从起点(第0组)开始,DFS找出到达终点(第m+1组)的路径。
接下来是第二个更加棘手的情况:
分析下面这张图:
1 K.... 2 ..... 3 ..s.. 4 ..... 5 ....T
从左上角到达右下角每一点的距离:
1 01234 2 12345 3 23556 4 34567 5 45678
发现一个重要规律!即如果能够不走有蛇的点,那么一定能找出一条同样短的路不经过有蛇点。也就是说,若是最短路中经过了有蛇点,那么这个点是必定要走的,否则另外找一条路花费的代价会比消灭这条蛇的1点时间更大,即例如出现下面这种情况。
1 K.... 2 ..... 3 #S##. 4 ..... 5 T....
穿越蛇点的代价肯定比绕开走要小。
然后看到题目特别指出最多只会出现5条蛇,于是就有了我下面的尝试算法:
1.将所有的蛇拿掉,做一次BFS+DFS操作,得到一个完成全程的最短距离ans;
2.放上一条蛇(把那个点标记为耗时2),再做一次BFS+DFS操作,得到一个完成全程的最短距离ans0。若ans0比ans更大,说明这个有蛇点是必须要经过的,记录一下,若ans0与ans相等则说明该点可以不经过,不影响结果;
3.拿掉之前的那条蛇,放上下一条蛇,并依此完成以上操作,判断每一个有蛇点是否都是必须经过的,不断记录即可。
最终答案为ans加上必须要经过的蛇点的个数
这里最为担心的是完成一次BFS+DFS操作需要的耗时问题,就像上面提到的,不用说极限情况,可能稍微接近一些极限的数据出来就会TLE,更不用说下面还要把这种操作再重复5次了。
幸运的是最后木有超...只能说出题的大大给的数据还没有到灭绝弱队的地步(哭)
hdu这道题有耗时更少的,一会再去找找其他神牛的题解好了。
1 /* *********************************************** 2 MYID : Chen Fan 3 LANG : G++ 4 PROG : D1004 5 ************************************************ */ 6 7 #include <iostream> 8 #include <cstdio> 9 #include <cstring> 10 #include <algorithm> 11 12 using namespace std; 13 14 typedef struct nod{ 15 int x,y; 16 } node; 17 node lis[11][1000]; 18 node q[20000]; 19 int an[11][1000][1000]; 20 int ma[110][110],num[110][110]; 21 bool flag[110][110]; 22 bool state[110][1000][6]; 23 bool done; 24 int ns; 25 node ss[6]; 26 27 int n,m,ans; 28 29 int dx[]={-1,0,1,0}; 30 int dy[]={0,-1,0,1}; 31 32 int doit(int sx,int sy,int ex,int ey) 33 { 34 int head=1,tail=1,ret=0; 35 q[head].x=sx; 36 q[head].y=sy; 37 memset(num,0,sizeof(num)); 38 memset(flag,0,sizeof(flag)); 39 flag[q[head].x][q[head].y]=true; 40 bool done=false; 41 while (head<=tail) 42 { 43 if (q[head].x==ex&&q[head].y==ey) 44 { 45 done=true; 46 ret=num[q[head].x][q[head].y]; 47 break; 48 } 49 for (int i=0;i<4;i++) 50 if (ma[q[head].x+dx[i]][q[head].y+dy[i]]&&(num[q[head].x+dx[i]][q[head].y+dy[i]]==0||num[q[head].x+dx[i]][q[head].y+dy[i]]>num[q[head].x][q[head].y]+ma[q[head].x+dx[i]][q[head].y+dy[i]])) 51 { 52 num[q[head].x+dx[i]][q[head].y+dy[i]]=num[q[head].x][q[head].y]+ma[q[head].x+dx[i]][q[head].y+dy[i]]; 53 if (!flag[q[head].x+dx[i]][q[head].y+dy[i]]) 54 { 55 tail++; 56 q[tail].x=q[head].x+dx[i]; 57 q[tail].y=q[head].y+dy[i]; 58 flag[q[head].x+dx[i]][q[head].y+dy[i]]=true; 59 } 60 } 61 flag[q[head].x][q[head].y]=false; 62 head++; 63 } 64 if (done) return ret; 65 else return -1; 66 } 67 68 void dfs(int s,int t,int tot) 69 { 70 if (s==m+1) 71 { 72 if (ans>tot) 73 { 74 ans=tot; 75 done=true; 76 } 77 return; 78 } 79 for (int i=1;i<=lis[s+1][0].x;i++) 80 if (an[s][t][i]!=-1) 81 { 82 dfs(s+1,i,tot+an[s][t][i]); 83 } 84 } 85 86 int main() 87 { 88 //freopen("D1004.txt","r",stdin); 89 90 scanf("%d%d",&n,&m); 91 while (!(n==0&&m==0)) 92 { 93 getchar(); 94 memset(ma,0,sizeof(ma)); 95 memset(lis,0,sizeof(lis)); 96 ns=0; 97 for (int i=1;i<=n;i++) 98 { 99 for (int j=1;j<=n;j++) 100 { 101 char c; 102 scanf("%c",&c); 103 switch(c) 104 { 105 case 'K': 106 lis[0][0].x=1; 107 lis[0][1].x=i;lis[0][1].y=j; 108 ma[i][j]=1; 109 break; 110 case 'T': 111 lis[m+1][0].x=1; 112 lis[m+1][1].x=i;lis[m+1][1].y=j; 113 ma[i][j]=1; 114 break; 115 case 'S': 116 ns++; 117 ss[ns].x=i;ss[ns].y=j; 118 ma[i][j]=1; 119 break; 120 case '.': 121 ma[i][j]=1; 122 break; 123 case '#': 124 break; 125 default: 126 ma[i][j]=1; 127 lis[c-'0'][0].x++; 128 lis[c-'0'][lis[c-'0'][0].x].x=i; 129 lis[c-'0'][lis[c-'0'][0].x].y=j; 130 } 131 } 132 getchar(); 133 } 134 135 ans=0; 136 memset(an,0,sizeof(an)); 137 for (int i=0;i<=m;i++) 138 { 139 for (int j=1;j<=lis[i][0].x;j++) 140 for (int k=1;k<=lis[i+1][0].x;k++) 141 an[i][j][k]=doit(lis[i][j].x,lis[i][j].y,lis[i+1][k].x,lis[i+1][k].y); 142 } 143 done=false; 144 ans=2147483647; 145 dfs(0,1,0); 146 if (done) 147 { 148 int ans0=ans; 149 int temp=0; 150 for (int p=1;p<=ns;p++) 151 { 152 if (p>1) ma[ss[p-1].x][ss[p-1].y]=1; 153 ans=0; 154 ma[ss[p].x][ss[p].y]=2; 155 memset(an,0,sizeof(an)); 156 for (int i=0;i<=m;i++) 157 { 158 for (int j=1;j<=lis[i][0].x;j++) 159 for (int k=1;k<=lis[i+1][0].x;k++) 160 an[i][j][k]=doit(lis[i][j].x,lis[i][j].y,lis[i+1][k].x,lis[i+1][k].y); 161 } 162 done=false; 163 ans=2147483647; 164 dfs(0,1,0); 165 if (ans>ans0) temp++; 166 } 167 printf("%d\n",ans0+temp); 168 } 169 else printf("impossible\n"); 170 171 scanf("%d%d",&n,&m); 172 } 173 174 return 0; 175 }