参考:http://blog.csdn.net/libin56842/article/details/41909459
【题意】:
一个人从(0,0)跑到(n,m),只有k点能量,一秒消耗一点,在图中有k个炮塔,给出炮塔的射击方向c,射击间隔t,子弹速度v,坐标x,y
问这个人能不能安全到达终点
要求:
1.人不能到达炮塔所在的坐标
2.炮塔会挡住子弹
3.途中遇到子弹是安全的,但是人如果停在这个坐标,而子弹也刚好到这个坐标,人就被射死
4.人可以选择停止不动
思路:其实不难,我们只需要看当人位于某个点的时候,其四个方向是否有炮塔,这个炮塔是都向人的方向射击,然后再看子弹是否刚好位于这个坐标即可。
而标记的话,vis[x][y][time],对于time时刻,人位于x,y的情况只需要访问一次,这是唯一的
【代码】
1 #include<iostream> 2 #include<cstdio> 3 #include<string> 4 #include<cstring> 5 #include<algorithm> 6 #include<cmath> 7 #include<queue> 8 9 using namespace std; 10 int m,n,k,d; 11 12 bool vis[1005][105][105]; 13 struct castle 14 { 15 int t,v; 16 char c; 17 }s[105][105]; 18 struct node 19 { 20 int x,y; 21 int step; 22 node(int xx,int yy,int ss):x(xx),y(yy),step(ss){} 23 }; 24 25 int dir[5][2]={{1,0},{-1,0},{0,1},{0,-1},{0,0}}; 26 void Init() 27 { 28 memset(vis,0,sizeof(vis)); 29 memset(s,0,sizeof(s)); 30 } 31 bool check(int x,int y) 32 { 33 if(x>=0&&x<=m&&y>=0&&y<=n) 34 { 35 return 1; 36 } 37 return 0; 38 } 39 void bfs() 40 { 41 queue<node> Q; 42 Q.push(node(0,0,0)); 43 vis[0][0][0]=1; 44 while(!Q.empty()) 45 { 46 node q=Q.front(); 47 Q.pop(); 48 if(q.step>d) 49 { 50 printf("Bad luck! "); 51 return; 52 } 53 if(q.x==m&&q.y==n) 54 { 55 printf("%d ",q.step); 56 return; 57 } 58 for(int i=0;i<5;i++) 59 { 60 node to=q; 61 to.x+=dir[i][0]; 62 to.y+=dir[i][1]; 63 to.step++; 64 if(!check(to.x,to.y)) 65 { 66 continue; 67 } 68 if(!vis[to.step][to.x][to.y]&&!s[to.x][to.y].t) 69 { 70 int life=1; 71 int dis; 72 //向北寻找 73 74 for(int k=to.x-1;k>=0;k--) 75 { 76 if(s[k][to.y].t) 77 { 78 if(s[k][to.y].c=='S') 79 { 80 dis=to.x-k; 81 if(dis%s[k][to.y].v) 82 { 83 break; 84 } 85 int tim=to.step-dis/s[k][to.y].v; 86 if(tim<0) 87 { 88 break; 89 } 90 if(tim%s[k][to.y].t) 91 { 92 break; 93 } 94 life=0; 95 break; 96 } 97 break; 98 } 99 } 100 if(life) 101 { 102 //向南 103 for(int k=to.x+1;k<=m;k++) 104 { 105 if(s[k][to.y].t) 106 { 107 if(s[k][to.y].c=='N') 108 { 109 dis=k-to.x; 110 if(dis%s[k][to.y].v) 111 { 112 break; 113 } 114 int tim=to.step-dis/s[k][to.y].v; 115 if(tim<0) 116 { 117 break; 118 } 119 if(tim%s[k][to.y].t) 120 { 121 break; 122 } 123 life=0; 124 break; 125 } 126 break; 127 } 128 } 129 } 130 if(life) 131 { 132 //向东 133 for(int k=to.y+1;k<=n;k++) 134 { 135 if(s[to.x][k].t) 136 { 137 if(s[to.x][k].c=='W') 138 { 139 dis=k-to.y; 140 if(dis%s[to.x][k].v) 141 { 142 break; 143 } 144 int tim=to.step-dis/s[to.x][k].v; 145 if(tim<0) 146 { 147 break; 148 } 149 if(tim%s[to.x][k].t) 150 { 151 break; 152 } 153 life=0; 154 break; 155 } 156 break; 157 } 158 } 159 } 160 if(life) 161 { 162 //向西 163 for(int k=to.y-1;k>=0;k--) 164 { 165 if(s[to.x][k].t) 166 { 167 if(s[to.x][k].c=='E') 168 { 169 dis=to.y-k; 170 if(dis%s[to.x][k].v) 171 { 172 break; 173 } 174 int tim=to.step-dis/s[to.x][k].v; 175 if(tim<0) 176 { 177 break; 178 } 179 if(tim%s[to.x][k].t) 180 { 181 break; 182 } 183 life=0; 184 break; 185 } 186 break; 187 } 188 } 189 } 190 if(life) 191 { 192 vis[to.step][to.x][to.y]=1; 193 Q.push(to); 194 } 195 196 } 197 198 199 } 200 } 201 202 } 203 int main() 204 { 205 while(~scanf("%d%d%d%d",&m,&n,&k,&d)) 206 { 207 Init(); 208 209 for(int i=0;i<k;i++) 210 { 211 char c[3]; 212 int t,v,x,y; 213 scanf("%s%d%d%d%d",c,&t,&v,&x,&y); 214 s[x][y].c=c[0]; 215 s[x][y].t=t; 216 s[x][y].v=v; 217 } 218 bfs(); 219 } 220 return 0; 221 }
【教训】
开始的时候是MLE,仔细查看了很久才反应过来,int vis[1005][105][105]数组开大了,1005*105*105/4/1000=44320kb,超出了题目限制32768kb,于是把int改成bool就A了。用sizeof操作符可以查看int占用4个字节,bool占用1个字节。以前做题从来不在意,都混着用.....以后还是要注意点....