bzoj4512[Usaco2016 Jan] Build Gates

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

posted @ 2016-08-03 13:50  YuanZiming  阅读(380)  评论(0编辑  收藏  举报