1049 棋盘染色
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 黄金 Gold
查看运行结果
题目描述 Description
有一个5×5的棋盘,上面有一些格子被染成了黑色,其他的格子都是白色,你的任务的对棋盘一些格子进行染色,使得所有的黑色格子能连成一块,并且你染色的格子数目要最少。读入一个初始棋盘的状态,输出最少需要对多少个格子进行染色,才能使得所有的黑色格子都连成一块。(注:连接是指上下左右四个方向,如果两个黑色格子只共有一个点,那么不算连接)
输入描述 Input Description
输入包括一个5×5的01矩阵,中间无空格,1表示格子已经被染成黑色。
输出描述 Output Description
输出最少需要对多少个格子进行染色
样例输入 Sample Input
11100
11000
10000
01111
11111
样例输出 Sample Output
1
数据范围及提示 Data Size & Hint
分类标签 Tags 点此展开
题解:
迭代加深搜
精髓:
只有把色块连通,改点才能被统计上;否则,tot会偏小。
因此,决定了当前这一坨点一定是一个连通块
AC代码:
#include<cstdio> #include<cstring> using namespace std; #define N 110 const int dx[]={0,0,1,-1}; const int dy[]={1,-1,0,0}; int n,sx,sy,tot,total; bool a[N][6],vis[N][6]; void check_dfs(int x,int y){//遍历全图,统计染色点数 tot++; vis[x][y]=1; for(int i=0;i<4;i++){ int nx=x+dx[i]; int ny=y+dy[i];//有的点只有被染色成连通块才会被统计到 if(!vis[nx][ny]&&nx>=1&&nx<=n&&ny>=1&&ny<=5&&a[nx][ny]) check_dfs(nx,ny); } } bool can(int x){ tot=0;//经过check_dfs后全图总共有tot个点被染色 memset(vis,0,sizeof vis); check_dfs(sx,sy); if(tot==total+x) return 1;//total为初始时染色点数,x为power_dfs之后多染的点数 return 0; } bool power_dfs(int x,int y,int now,int sum){//前两维为坐标,now表示当前比初始状态多涂了now个点,sum表示本次搜素的目标是涂sum个 if(now==sum){ if(can(sum)) return 1;//判断是否已联通 return 0; } for(int j=y+1;j<=5;j++){//扫当前点的该行的右边 if(!a[x][j]){ a[x][j]=1; if(power_dfs(x,j,now+1,sum)) return 1; a[x][j]=0; } } for(int i=x+1;i<=n;i++){//扫当前点的下方、左下方、右下方的所有区域 for(int j=1;j<=5;j++){ if(!a[i][j]){ a[i][j]=1; if(power_dfs(i,j,now+1,sum)) return 1; a[i][j]=0; } } } return 0; } int main(){ //scanf("%d",&n);//先做的棋盘染色2,懒得改了,见谅 n=5; for(int i=1;i<=n;i++){ for(int j=1;j<=5;j++){ scanf("%1d",&a[i][j]); if(a[i][j]){ total++; sx=i;sy=j; } } } for(int i=0;i<=5*n;i++){ if(power_dfs(1,1,0,i)){ printf("%d\n",i); return 0; } } return 0; }
时间: 2024-11-07 18:34:13