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.
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.
For each test case, output minimum steps to reach the goal. If you can’t reach the goal, output -1 instead.
3
1 1 0
1 0 1
0 1 1
3
2 3 1
2 2 1
0 1 0
2
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; }
發現問題內部存在的關係 將大大簡化問題
這題比賽的時候也不會寫,思路出不來的感覺
按照第一種方法 在比賽的時候幾乎寫不出來
加強編碼能力是關鍵