bzoj4512[Usaco2016 Jan] Build Gates
题意:
某人从农场的(0,0)出发,沿边界到处乱走,走过的地方会留下栅栏,等走完后问要在多少个栅栏上开门才能使整个农场连通,最多走1000步。
题解:
我的代码比别人的都长~我的做法是先算出最左/最下可能会走到哪里,然后变换一下坐标系(实际是是改变出发起点),然后记录哪个格子的上下左右被栅栏堵了,最后做一下floodfill,输出连通块数-1。注意还要把有栅栏区域的外圈格子也算进去,因为它们代表了有栅栏区域外的广大地区(这个人的农场是无限大的)。
代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define inc(i,j,k) for(int i=j;i<=k;i++) 5 using namespace std; 6 7 bool unok[2000][2000][4],vis[2000][2000]; int mx,my,tot,n; 8 char opt[2000]; 9 void dfs(int x,int y){ 10 vis[x][y]=1; 11 if(y!=0&&!unok[x][y][0]&&!vis[x][y-1])dfs(x,y-1); 12 if(x!=mx&&!unok[x][y][1]&&!vis[x+1][y])dfs(x+1,y); 13 if(y!=my&&!unok[x][y][2]&&!vis[x][y+1])dfs(x,y+1); 14 if(x!=0&&!unok[x][y][3]&&!vis[x-1][y])dfs(x-1,y); 15 } 16 int main(){ 17 scanf("%d",&n); int x=1,y=1; scanf("%s",opt); 18 inc(i,0,n-1){if(opt[i]=='W')y++;if(opt[i]=='S')x++;} 19 memset(unok,0,sizeof(unok)); mx=my=0; 20 inc(i,0,n-1){ 21 if(opt[i]=='N'){ 22 unok[x][y][0]=1; unok[x][y-1][2]=1; x++; mx=max(mx,x); 23 } 24 if(opt[i]=='S'){ 25 unok[x-1][y][0]=1; unok[x-1][y-1][2]=1; x--; 26 } 27 if(opt[i]=='W'){ 28 unok[x][y-1][3]=1; unok[x-1][y-1][1]=1; y--; 29 } 30 if(opt[i]=='E'){ 31 unok[x][y][3]=1; unok[x-1][y][1]=1; y++; my=max(my,y); 32 } 33 } 34 memset(vis,0,sizeof(vis)); tot=0; 35 inc(i,0,mx)inc(j,0,my)if(!vis[i][j])tot++,dfs(i,j); 36 printf("%d",tot-1); 37 return 0; 38 }
20160517