7_7_2013 C.An Easy Puz

Problem C: An Easy Puz

Time Limit: 1 Sec   Memory Limit: 32 MB
Submit: 17   Solved: 10
[ Submit][ Status][ Web Board]

Description

Wddpdh find an interesting mini-game in the BBS of WHU, called “An easy PUZ”. It’s a 6 * 6 chess board and each cell has a number in the range of 0 and 3(it can be 0, 1, 2 or 3). Each time you can choose a number A(i, j) in i-th row and j-th column, then the number A(i, j) and the numbers around it (A(i-1, j), A(i+1, j),A(i, j-1),A(i, j+1), sometimes there may just be 2 or 3 numbers.) will minus 1 (3 to 2, 2 to 1, 1 to 0, 0 to 3). You can do it finite times. The goal is to make all numbers become 0. Wddpdh now come up with an extended problem about it. He will give you a number N (3 <= N <= 6) indicate the size of the board. You should tell him the minimum steps to reach the goal.

Input

The input consists of multiple test cases. For each test case, it contains a positive integer N(3 <= n <= 6)N lines follow, each line contains N columns indicating the each number in the chess board.

Output

For each test case, output minimum steps to reach the goal. If you can’t reach the goal, output -1 instead.

Sample Input

1 1 0 

1 0 1 

0 1 1 

2 3 1 

2 2 1 

0 1 0

Sample Output

3


#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;

int mat[10][10],rm[10][10],tr[10][10];
int ans;
int n;
int dx[]={0, -1, 1, 0, 0};
int dy[]={0, 0, 0, -1, 1};

void
fix(int &u, int v)
{
    u +=v;
    u=((u%4)+4)%4;
}

bool inboard(int x, int y)
{
    return 0<=x && x<n && 0<=y && y<n;
}

void update()
{
    memcpy(rm, mat, sizeof(rm));
    for(int i=0; i<n; i++){
        for(int j=0; j<n; j++){
            for(int dir=0; dir<5; dir++){
                int x= j+ dx[dir];
                int y= j+ dy[dir];
                if(!inboard(x, y))continue;
                fix(rm[x][y], -tr[i][j]);
            }
        }
        if(i+1<=n){
            for(int j=0; j<n; j++){
                tr[i+1][j]=rm[i][j];
            }
        }
    }
    for(int i=0; i<n; i++){
        for(int j=0; j<n; j++){
            if(rm[i][j])
                return;
        }
    }
    int sum=0;
    for(int i=0; i<n; i++){
        for(int j=0; j<n; j++){
            sum+=tr[i][j];
        }
    }
    if(ans==-1 || ans>sum) ans=sum;
}

void
dfs(int x)
{
    if(x==n){
        update();
        return ;
    }
    for(int i=0; i<4; i++){
        tr[0][x]=i;
        dfs(x+1);
    }
}



int
main()
{
    int n;
    while(cin>>n){
        for(int i=0; i<n; i++){
            for(int j=0; j<n; j++){
                    cin>>mat[i][j];
            }
        }
        ans=-1;
        dfs(0);
        cout<<ans<<endl;

    }
    return 0;

}
更好的方法

#include <stdio.h>
 int a[10][10],n,c[10],min;
 void Judge()
 {
     int t[2][10]={0},i,j,sum=0;
     for(i=1;i<=n;i++)t[1][i]=c[i],sum+=c[i];
     for(i=2;i<=n;i++)
         for(j=1;j<=n;j++)
         {
             int l=i&1;
             int r=1-l;
             t[l][j]=( a[i-1][j]+12-t[r][j]-t[r][j-1]-t[r][j+1]-t[l][j] )%4;//神級關係式,各種簡化

             sum+=t[l][j];
         }
     for(i=1;i<=n;i++)
     {
         int l=n&1;
         int r=1-l;
         if( (a[n][i]+12-t[l][i]-t[l][i-1]-t[l][i+1]-t[r][i])%4!=0 )break;//n=n+1即判斷最後有無歸零
     }
     if(i==n+1 && min>sum) min=sum;
 }
 void dfs(int x)
 {
     if(x==n+1)
     {
         Judge();
         return;
     }
     for(int i=0;i<=3;i++)
     {
         c[x]=i;
         dfs(x+1);
     }
 }
 int main()
 {
     int i,j;
     while( scanf("%d",&n)==1 )
     {
         min=999;
         for(i=1;i<=n;i++)
             for(j=1;j<=n;j++)
                 scanf("%d",&a[i][j]);
         dfs(1);
         printf("%d\n",min);
     }
     return 0;
 }

發現問題內部存在的關係 將大大簡化問題

這題比賽的時候也不會寫,思路出不來的感覺

按照第一種方法 在比賽的時候幾乎寫不出來

加強編碼能力是關鍵

你可能感兴趣的:(7_7_2013 C.An Easy Puz)