Description
你的蔬菜园形成了一个矩形网格。你决定检查一些小块土地。从左上角开始,你将走过菜园,回到起点。现在你想要检查一下菜园内的田地,于是你决定从左上角出发,在菜园里走一圈回到原处。最后,所有在你走过的这个环内的田地都被认为检查过了。为了保护植 物,你的路径只能在田地边界的小路上走,不能走到田地里面。并且你走过的路径不能自交,小路保证足够宽,你可以多次沿着一条小路走,并且这些路径都不相 交。先在给你菜园的地图,其中有的田地标记为”I”,表示这些田地是你想要检查的;有的田地被标记为”X”,表示这些田地是你不想检查的;有的田地被标记为”.”,表示这些田地你不关心。假设菜园中有K个”I”,那么你要返回K个数字,其中第i个数为:恰好检查任意i个标记为”I”的田地,并且没有检查任何一个标记为”X”的田地的最短路。
【输入格式】
n 行,每行 m 个字符。
'I'表示重要的格子,'X'表示有坏处的格子,'.'表示其他格子。
【输出格式】
输出重要的格子数行,第 i 行表示圈住 i 个重要的格子的最小
路径长度。
【输入样例】
X.I
.I.
I..
【输出样例】
8
10
14
判断一个格子是否被圈住,可以看它上面是否有奇数条边
如果是奇数,那么就需要从下面连回起点
用$dist[x][y][S]$表示到$(x,y)$,关键点上面的边数的奇偶性状态S
广搜更新$dist$数组
复杂度$O(n^{2}*10*2^{10})$
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 #include<queue> 7 using namespace std; 8 struct ZYYS 9 { 10 int x,y,s; 11 }; 12 const int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0}; 13 int n,m,cnt,x[11],y[11],pd[11],dist[51][51][1<<11],ans[11],inf,tot,Max; 14 bool vis[51][51][1<<11]; 15 char s[51][51]; 16 queue<ZYYS>Q; 17 int get(int S,int xx,int yy) 18 {int i; 19 for (i=1;i<=cnt;i++) 20 { 21 if (yy==y[i]&&xx<=x[i]) S^=(1<<i-1); 22 } 23 return S; 24 } 25 int main() 26 {int i,j; 27 while (~scanf("%s",s[n])) 28 { 29 n++; 30 } 31 m=strlen(s[0]); 32 for (i=0;i<n;i++) 33 for (j=0;j<m;j++) 34 { 35 if (s[i][j]=='X') 36 { 37 ++cnt; 38 pd[cnt]=0; 39 x[cnt]=i;y[cnt]=j; 40 } 41 else if (s[i][j]=='I') 42 { 43 ++cnt; 44 pd[cnt]=1; 45 x[cnt]=i;y[cnt]=j; 46 } 47 } 48 memset(dist,127/2,sizeof(dist)); 49 Q.push((ZYYS){0,0,0}); 50 dist[0][0][0]=0; 51 while (Q.empty()==0) 52 { 53 ZYYS u=Q.front(); 54 Q.pop(); 55 vis[u.x][u.y][u.s]=0; 56 for (i=0;i<4;i++) 57 { 58 int x=u.x+dx[i],y=u.y+dy[i],S; 59 if (x<0||y<0||x>n||y>m) continue; 60 if (i==0||i==1) 61 S=get(u.s,u.x,min(y,u.y)); 62 else S=u.s; 63 if (dist[x][y][S]>dist[u.x][u.y][u.s]+1) 64 { 65 dist[x][y][S]=dist[u.x][u.y][u.s]+1; 66 if (vis[x][y][S]==0) 67 { 68 vis[x][y][S]=1; 69 Q.push((ZYYS){x,y,S}); 70 } 71 } 72 } 73 } 74 memset(ans,127/2,sizeof(ans)); 75 inf=ans[0]; 76 for (i=1;i<(1<<cnt);i++) 77 { 78 tot=0; 79 for (j=1;j<=cnt;j++) 80 if ((i&(1<<j-1))) 81 { 82 if (pd[j]==0) 83 { 84 tot=-1; 85 break; 86 } 87 else 88 tot++; 89 } 90 if (tot!=-1) 91 { 92 Max=max(tot,Max); 93 if (dist[0][0][i]<ans[tot]) ans[tot]=dist[0][0][i]; 94 } 95 } 96 for (i=1;i<=Max;i++) 97 printf("%d\n",ans[i]); 98 }