第三届 山东省ACM省赛 Mine Number

http://www.sdutacm.org/sdutoj/problem.php?action=showproblem&problemid=2410

只要是第一行确定了,全部棋局也就确定了,dfs搜索第一行的情况,然后后面的直接根据上一行而定,这样最后就能得出整个矩阵了,第一行最多20个,也就是复杂度为2^20,不会超时,并且中间还会有剪枝。

但是苦逼的是当时模拟的时候感觉dfs没什么用,只要第一行确定了其他就能确定的话,我直接二进制分解获得第一行就行了,但是这样做了好久,却不是TL就是WR,至今不知道为何,以后有时间了再看吧。。。(顺便也贴下第一次二进制分解的错误方法。。)


#include <iostream>  
#include <cstdio>  
#include <string>  
#include <cstring>  
#define MAX 500  
using namespace std;  
char ch[100][100],res[100][100];  
int T,n,m;  
int dir[][2]= {{-1,0},{1,0},{0,-1},{0,1},{0,0}};  
int mark=0;  
  
bool OK(int x,int y){  
  int tempx,tempy;  
  for(int i=0;i<5;i++){  
    tempx=x+dir[i][0],tempy=y+dir[i][1];  
    if( (tempx<0 || tempx>=n || tempy<0 || tempy>=m) || ch[tempx][tempy]>='1')  
        continue;  
    else return false;  
  }  
  return true;  
}  
  
void update(int x,int y,int num){  
  for(int i=0;i<4;i++){  
     int tempx=dir[i][0]+x , tempy=dir[i][1]+y;  
          if( tempx >= 0 && tempx < n && tempy>=0 &&tempy<m )  
              ch[tempx][tempy]+=num;  
    }  
  ch[x][y]+=num;  
}  
  
  
void printres(){  
  for(int i=0; i<n; i++)  
    {  
        for(int j=0; j<m; j++)  
            printf("%c",res[i][j]);  
        printf("
");  
    }  
}  
  
  
bool judge(){  
  for(int i=0;i<m;i++)  
    if(ch[n-1][i]!='0')  
      return false;  
  return true;  
}  
  
void dfs(int x,int y){  
  if(y>=m) x++,y=0;  
  if( x==n && y==0 ){  
    if(judge()){  
        printres();  
        mark=1;  
    }  
  }  
  if( x<0 || x>=n || mark==1) return ;  
  if(x==0){  
      if( OK(x,y) ){  
            update(x,y,-1);  
            res[x][y]='*';  
            dfs(x,y+1);  
            update(x,y,1);  
            res[x][y]='?';  
      }  
      res[x][y]='.';  
      dfs(x,y+1);  
    return ;  
  }  
  
  if( ch[x-1][y] !='0' && ch[x-1][y] !='1' )  
    return ;  
  if(ch[x-1][y]=='1'){  
    res[x][y]='*';  
    update(x,y,-1);  
    dfs(x,y+1);  
    update(x,y,1);  
    res[x][y]='?';  
  }  
else{
  res[x][y]='.';  
  dfs(x,y+1); 
} 
  return ;  
}  
  
  
int main ()  
{  
    char dev[100];  
    int coun=1;  
    scanf("%d",&T);  
    while(T--)  
    {  
        mark=0;  
        scanf("%d%d",&n,&m);  
        for(int i=0; i<n; i++)  
            scanf("%s",&ch[i]);  
        printf("Case %d:
",coun++);  
        dfs(0,0);  
    }  
  
    return 0;  
} 


#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#define MAX 500
using namespace std;
char ch[100][100],temp[100][100],res[100][100];
int T,n,m;
int dir[][2]= {{-1,0},{1,0},{0,-1},{0,1}};

bool Ok(int tempm){
  return temp[0][tempm]=='0' || (tempm!=0&&temp[0][tempm-1]=='0') || (tempm+1<m&&temp[0][tempm+1]=='0'); ///|| (1<n&&temp[1][tempm]=='0')
}


int main ()
{
    char dev[100];
    int coun=1;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(int i=0; i<n; i++)
            scanf("%s",&ch[i]);
        int x=(1<<m);
        printf("Case %d:
",coun++);
        int last=n-1;
        for(int ss=x-1; ss>=0; ss--)
        {
            int mark=1;
            int tempm=m-1;
            for(int j=0; j<m; j++)
                res[0][j]='.';
            for(int i=0; i<=n-1; i++)
                strcpy(temp[i],ch[i]);

            int tempss=ss;
            for(; tempss>0; tempm--)
            {
                if(tempss%2)
                {
                    res[0][tempm]='*';
                    if(Ok(tempm))
                    {
                        mark = 0;
                        last=2;
                        break;
                    }
                    temp[0][tempm]--;
                    if(tempm-1>=0) temp[0][tempm-1]--;
                    if(tempm+1<m) temp[0][tempm+1]--;
                    if(1<n) temp[1][tempm]--;
                }
                tempss/=2;
            }

            for(int i=1; i<n  &&  mark  ; i++)
                for(int j=0; j<m  &&  mark; j++)
                {
                    if( temp[i-1][j]!='0' && temp[i-1][j]!='1' )
                    {
                        mark=0;
                        last=min(n-1,i+2);
                        break;
                    }
                    res[i][j]='.';
                    if(temp[i-1][j]=='1')
                    {
                        res[i][j]='*';
                        for(int xxx=0; xxx<4; xxx++)
                            if(i+dir[xxx][0]>=0 && i+dir[xxx][0]<m && j+dir[xxx][1]>=0  && j+dir[xxx][1]<m)
                            {
                                if(temp[  i+dir[xxx][0]  ][ j+dir[xxx][1] ]<='0')
                                {
                                    mark=0;
                                    last=min(n-1,i+2);
                                    break;
                                }
                                temp[  i+dir[xxx][0]  ][ j+dir[xxx][1] ]--;
                            }
                        temp[i][j]--;
                    }
                }
            if(mark==1)
            {
                for(int i=0; i<m&&mark; i++) ///判断最后一行
                    if(temp[n-1][i]!='0')
                        mark=0,last=n-1;

                for(int i=0; i<n&&mark; i++)
                {
                    for(int j=0; j<m; j++)
                        printf("%c",res[i][j]);
                    printf("
");
                }
                if(mark){
                   break;
                }
            }
        }
    }

    return 0;
}




原文地址:https://www.cnblogs.com/zswbky/p/6718004.html