標籤:blog io os ar for 2014 sp on log
(北京網路賽09題)題意:給一矩陣(圖),裡面有起點,終點,還有探照燈(每個有初始朝向,每秒順時針轉90度),前面有燈或者自己被燈照著,移動就要花3秒,求起點到終點最短時間。
用一個數組三維數組記錄一下,用來當前位置目前時間%4有沒有燈,然後優先隊列(時間短的在前面),搜尋即可。考慮到可以來回走或者原地等,不能簡單判重剪枝:每個地方最多是4種狀態!就是4秒之後就全圖狀態回到一樣!所以若目前狀態(時間%4)下來過就不用來了。
#include<iostream>#include<vector>#include<cstdio>#include<algorithm>#include<cstring>#include<string>#include<queue>#include<cmath>using namespace std;struct xy{ int x,y; int times; bool operator <(const xy &ttt)const { return ttt.times<times; }};int n;int a[505][505];int b[505][505][4];int vis[505][505][4];int f[4][2]={-1,0,0,1,1,0,0,-1};xy ss; int mints;void bfs(){ priority_queue<xy>q; q.push(ss); while(!q.empty()) { xy cur=q.top(); q.pop(); if(a[cur.x][cur.y]==4&&cur.times<mints) { mints=cur.times;break; } xy next1=cur; next1.times=cur.times+1; if(vis[next1.x][next1.y][next1.times%4]==0) { vis[next1.x][next1.y][next1.times%4]=1; q.push(next1); } for(int i=0;i<4;i++) { xy next; next.x=cur.x+f[i][0]; next.y=cur.y+f[i][1]; if(next.x>=0&&next.y>=0&&next.x<n&&next.y<n&&a[next.x][next.y]!=0) { if(b[next.x][next.y][cur.times%4]==1||b[cur.x][cur.y][cur.times%4]==1) { next.times=cur.times+3; if(vis[next.x][next.y][next.times%4]==0) { vis[next.x][next.y][next.times%4]=1; q.push(next); } } else { next.times=cur.times+1; if(vis[next.x][next.y][next.times%4]==0) { vis[next.x][next.y][next.times%4]=1; q.push(next); } } } } }}int main(){ int T; scanf("%d",&T);int cnt=1; while(T--) { scanf("%d",&n); memset(b,-1,sizeof(b)); memset(vis,0,sizeof(vis)); char tx;char sss[505]; for(int i=0;i<n;i++) { scanf("%s",sss); for(int j=0;j<n;j++) { tx=sss[j]; if(tx=='.') { a[i][j]=1; } else if(tx=='T') { a[i][j]=4; } else if(tx=='M') { a[i][j]=1; ss.x=i;ss.y=j; ss.times=0; } else if(tx=='#') { a[i][j]=0; } else if(tx=='N') { a[i][j]=2; for(int k=0;k<4;k++) { int xx=i+f[k][0]; int yy=j+f[k][1]; b[i][j][k]=1; if(xx>=0&&yy>=0&&xx<n&&yy<n) { b[xx][yy][k]=1; } } } else if(tx=='E') { a[i][j]=2; for(int k=0;k<4;k++) { int xx=i+f[k][0]; int yy=j+f[k][1]; b[i][j][k]=1; if(xx>=0&&yy>=0&&xx<n&&yy<n) { int ii=k; if(ii==0)ii=3; else ii--; b[xx][yy][ii]=1; } } } else if(tx=='S') { a[i][j]=2; for(int k=0;k<4;k++) { int xx=i+f[k][0]; int yy=j+f[k][1]; b[i][j][k]=1; if(xx>=0&&yy>=0&&xx<n&&yy<n) { int ii=k; if(ii==0||ii==1)ii=ii+2; else ii=ii-2; b[xx][yy][ii]=1; } } } else if(tx=='W') { a[i][j]=2; for(int k=0;k<4;k++) { int xx=i+f[k][0]; int yy=j+f[k][1]; b[i][j][k]=1; if(xx>=0&&yy>=0&&xx<n&&yy<n) { int ii=k; if(ii==3)ii=0; else ii++; b[xx][yy][ii]=1; } } } } } mints=0x3f3f3f3f; vis[ss.x][ss.y][ss.times]=1; bfs(); printf("Case #%d: ",cnt++); if(mints==0x3f3f3f3f) { printf("-1\n"); } else { printf("%d\n",mints); } } return 0;}
hdu 5040 優先隊列BFS+剪枝