1050 棋盘染色 2

1050 棋盘染色 2

 

 时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 大师 Master
 
 
 
题目描述 Description

有一个5*N的棋盘,棋盘中的一些格子已经被染成了黑色,你的任务是对最少的格子染色,使得所有的黑色能连成一块。

输入描述 Input Description

第一行一个整数N(<=100),接下来N行每行一个长度为5的01串,1表示所在格子已经被染成了黑色,0表示所在格子没有被染色。

输出描述 Output Description

第一行一个整数N(<=100),接下来N行每行一个长度为5的01串,1表示所在格子已经被染成了黑色,0表示所在格子没有被染色。

样例输入 Sample Input

5
11100
11000
10000
01111
11111

样例输出 Sample Output

1

数据范围及提示 Data Size & Hint

N(<=100)

 

70分代码,TLE了4个点

原理:用棋盘染色1(搜索)

70代码:

#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;
    memset(vis,0,sizeof vis);
    check_dfs(sx,sy);
    if(tot==total+x) return 1;
    return 0;
}
bool power_dfs(int x,int y,int now,int 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);
    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;
}

AC代码:(状压dp超noip范围,代码又那么长,看一眼就困了)

自行百度

posted @ 2016-08-17 17:37  神犇(shenben)  阅读(226)  评论(0编辑  收藏  举报