【题目描述】
有一个5*N的棋盘,棋盘中的一些格子已经被染成了黑色,你的任务是对最少的格子染色,使得所有的黑色能连成一块。
【输入描述】
第一行一个整数N(N <= 100),接下来N行每行一个长度为5的01串,1表示所在格子已经被染成了黑色,0表示所在格子没有被染色。
【输出描述】
输出一个整数,表示最少需要染色的格子数。
【样例输入】
5
11100
11000
10000
01111
11111
【样例输出】
1
70分迭代搜索(原谅我蒟蒻):
源代码: #include<cstdio> #include<cstring> int x[4]={0,0,1,-1},y[4]={1,-1,0,0}; int n,t1,t2,Num,Total; bool f[105][6],Vis[105][6]; void Check(int X,int Y) //遍历全图,统计染色点数。 { Num++; Vis[X][Y]=true; for(int a=0;a<4;a++) { int T1=X+x[a]; int T2=Y+y[a]; //精髓,有的点只有被染色成连通块才会被统计到。 if (!Vis[T1][T2]&&T1>=1&&T1<=n&&T2>=1&&T2<=5&&f[T1][T2]) Check(T1,T2); } } bool Can(int t) //判断是否合法。 { Num=0; //经过Check()后全图总共有Num个点被染色。 memset(Vis,false,sizeof(Vis)); Check(t1,t2); //从最后搜索,挺方便。 if (Num==Total+t) return true; //Total为初始时染色点数,t为DFS()之后多染的点数。 return false; } bool DFS(int X,int Y,int Now,int Sum) //迭代搜索,X、Y为坐标,Now表示当前比初始状态多涂了Now个点,Sum表示目标是涂Sum个点。 { if (Now==Sum) //到达极限。 { if (Can(Sum)) return true; //判断是否已连通。 return false; } for (int a=Y+1;a<=5;a++) //搜索并连接节点的该行的右边。 if (!f[X][a]) { f[X][a]=true; if (DFS(X,a,Now+1,Sum)) return true; f[X][a]=false; } for (int a=X+1;a<=n;a++) //同理于上,搜索节点所在行的下方所有区域。 for (int b=1;b<=5;b++) if (!f[a][b]) { f[a][b]=true; if (DFS(a,b,Now+1,Sum)) return true; f[a][b]=false; } return false; //依旧不成立。 } int main() { scanf("%d",&n); for (int a=1;a<=n;a++) for (int b=1;b<=5;b++) { scanf("%1d",&f[a][b]); //真是太神奇了,"%Xd"表示读入X位数,也可忽略空格。 if (f[a][b]) { Total++; //黑格总数。 t1=a; //最后的黑格。 t2=b; } } for (int a=0;a<=5*n-Total;a++) //迭代。 if (DFS(1,1,0,a)) { printf("%d",a); return 0; } }