POJ3279-Fliptile

题目链接:POJ3279

思路很重要。

第一点,N最大只有15 ,考虑到第一排的翻转情况确定之后,整个棋盘的翻转情况也就确定了。最多遍历2^15种。

第二点,对于每一排的1,只有其下面的翻转能将其变为0,而不影响同行其他棋子的翻转情况。

第三点,坐标系的建立要统一,x,y,m,n,  x指的是row 那么y指的是col ,都统一用一个坐标系不容易错。

这题目的思路值得借鉴,思考。不看他人的题解,我也想不到。

AC代码;

#include<stdio.h>
#include<string.h>
const int maxn=20;
bool mp[maxn][maxn],ans[maxn][maxn],f[maxn][maxn],tmp[maxn][maxn];
int m,n,res=300;

void flip(int x,int y){
    tmp[x][y]=!tmp[x][y];
    if(x-1>=0) tmp[x-1][y]=!tmp[x-1][y];
    if(x+1<m) tmp[x+1][y]=!tmp[x+1][y];
    if(y-1>=0) tmp[x][y-1]=!tmp[x][y-1];
    if(y+1<n) tmp[x][y+1]=!tmp[x][y+1];
}

void print(bool t[maxn][maxn]){
  //  puts("");
    for(int i=0;i<m;i++){
        for(int j=0;j<n;j++){
            printf("%d ",t[i][j]);
        }puts("");
    }
  //  puts("");
}

int main(){
    scanf("%d%d",&m,&n);
    for(int i=0;i<m;i++){
        for(int j=0;j<n;j++)
            scanf("%d",&mp[i][j]);
    }
    /*
   // check input
  // memcpy(f,mp,sizeof(mp));
    for(int i=1;i<=m;i++){
        for(int j=1;j<=n;j++){
            printf("%d ",f[i][j]);
        }puts("");
    }
  //  */
    for(int i=0;i<(1<<n);i++){
     //   memcpy(f,mp,sizeof(mp));
     memset(f,false,sizeof(f));
     //printf("%d:",i);
        for(int j=0;j<n;j++){
            f[0][n-j-1]=(i>>j)&1;
           // printf("%d ",f[0][n-j-1]);
        }
      //  for(int j=0;j<n;j++) printf("%d ",f[0][j]);puts("");
        int fcnt=0;
        memcpy(tmp,mp,sizeof(mp));
        for(int j=0;j<n;j++){
            if(f[0][j]){
                flip(0,j);
                fcnt++;
            }
        }
        for(int j=0;j<m-1;j++){
            for(int k=0;k<n;k++){
                if(tmp[j][k]==1){
                    f[j+1][k]=1;
                    flip(j+1,k);
                    fcnt++;

                 //  if(i==0) printf("%d,%d\n",j+1,k);
                  // if(i==0) print(tmp);
                }
            }
        }
       // printf("fcnt=%d\n",fcnt);
        bool flag=true;
        for(int j=0;j<n;j++){
            if(tmp[m-1][j]) flag=false;
           // printf("%d ",tmp[m-1][j]);
        }
        //puts("");

        if(!flag) continue;
        else{
            if((fcnt<res)){
                memcpy(ans,f,sizeof(f));
                res=fcnt;
            }
        }
    }
   // printf("res:%d\n",res);

    memcpy(tmp,mp,sizeof(mp));
    if(res!=300) print(ans);
    else printf("IMPOSSIBLE\n");
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值