USACO-Overfencing
来源:http://ace.delos.com/usacoprob2?a=M7C67j8aT97&S=maze1
这题构图是个麻烦。
声明一点:我的构图法不值得借鉴
我把图中的每个点编号,记录每个点与上下左右的连通性,然后用DFS搜索距离。
效率很低,而且构图时特别烦。
但是好处就是DFS很容易写,而且算法也很简单。
当然这题解法很多,DFS能行的BFS一般没问题,当然Dijkstra算法也是行的,听说Flood-Fill算法也行
/* ID:ay27272 PROG:maze1 LANG:C++ */ #include <iostream> #include <cstdio> #include <cstring> using namespace std; bool map[4000][4]={0}; //0表示上,1表示左,顺时针 int w,h; int x1,x2,y1,y2,maxx; int vis[4000],d[4000]; void dfs(int s,int step) { maxx=max(maxx,step); vis[s]=step; if (map[s][0] && (!vis[s-w] || vis[s-w]>step+1)) dfs(s-w,step+1); if (map[s][1] && (!vis[s+1] || vis[s+1]>step+1)) dfs(s+1,step+1); if (map[s][2] && (!vis[s+w] || vis[s+w]>step+1)) dfs(s+w,step+1); if (map[s][3] && (!vis[s-1] || vis[s-1]>step+1)) dfs(s-1,step+1); } int main() { freopen("maze1.in","r",stdin); freopen("maze1.out","w",stdout); x1=x2=y1=y2=0; char ch; cin>>w>>h; for (int i=1;i<=2*h+1;i++) //按行编号 for (int j=1;j<=2*w+1;j++) { scanf("%c",&ch); if (ch=='\n') scanf("%c",&ch); if (ch!=' ') continue; if (i%2==0) { if (j%2!=0) map[(i/2-1)*w+j/2][1]=map[(i/2-1)*w+j/2+1][3]=true; if (j==1) //出口有可能在最左边 { if (x1) {x2=i; y2=j+1;} else {x1=i; y1=j+1;} map[(i/2-1)*w+j/2][1]=map[(i/2-1)*w+j/2+1][3]=false; } if (j==2*w+1) //出口在最右边 { if (x1) {x2=i; y2=j;} else {x1=i; y1=j;} map[(i/2-1)*w+j/2][1]=map[(i/2-1)*w+j/2+1][3]=false; } } else { map[(i/2-1)*w+j/2][2]=map[(i/2)*w+j/2][0]=true; if (i==1) //出口在最上边 { if (x1) {x2=i+1; y2=j;} else {x1=i+1; y1=j;} map[(i/2-1)*w+j/2][2]=map[(i/2)*w+j/2][0]=false; } if (i==2*h+1) //最下边 { if (x1) {x2=i; y2=j;} else {x1=i; y1=j;} map[(i/2-1)*w+j/2][2]=map[(i/2)*w+j/2][0]=false; } } } memset(vis,0,sizeof(vis)); dfs((x1/2-1)*w+y1/2,1); for (int i=1;i<=w*h;i++) d[i]=vis[i]; memset(vis,0,sizeof(vis)); dfs((x2/2-1)*w+y2/2,1); maxx=0; for (int i=1;i<=w*h;i++) maxx=max(maxx,min(vis[i],d[i])); cout<<maxx<<endl; return 0; }