http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=&problem=2459
明天省赛,所以今天做几道所谓水题,可惜这个题因为输出写错WA了很久,,,
如果直接枚举矩阵所有的位置是否改变,那么时间复杂度是承受不住的
这道题让我学到的,就是:
1、遇到题先手算模拟,然后尝试找规律吧。这道题的规律就是:第一行一旦确定,那么整个矩阵就可以确定,所以枚举第一行,还可以的
2、if else 一定把所有的情况逻辑都理清,这题Debug的时候稍微变了下写法,又WA了很久,代码也贴在后面了。Debug的时候,重用代码的时候好好理理思路,很可能是老思路跟新思路的差异产生新的bug
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int MAXN = 20; //const int INF = 0x3fffffff;999 const int INF = 1000000000; int n,a[MAXN][MAXN],b[MAXN][MAXN]; int Judge(int m) { //memset(b,0,sizeof(b)); int tmp=0; for(int i=0;i<n;i++) for(int j=0;j<n;j++) b[i][j]=a[i][j]; for(int i=0;i<n;i++) /**/ { if((m & (1<<i))) { if(0 == b[0][i]) { b[0][i]=1; /*有1表示do*/ tmp++; } else return INF; } } for(int i=1;i<n;i++) for(int j=0;j<n;j++) { int sum=b[i][j]; if(j-1>=0)sum+=b[i-1][j-1]; if(j+1<n)sum+=b[i-1][j+1]; if(i-2>=0)sum+=b[i-2][j]; if(sum%2) { if(!b[i][j]) { b[i][j]=1; tmp++; } else return INF; } } // 这种写法是有问题的,因为 /*以上的步骤都没有检测最后一行,一下测试最后一行*/ for(int i=0;i<n;i++) { int sum=0; if(n-2>=0)sum+=b[n-2][i]; if(i>0)sum+=b[n-1][i-1]; if(i+1<n)sum+=b[n-1][i+1]; if(sum%2)return INF; } return tmp; } int main() { int ncase; scanf("%d",&ncase); //while(n--) for(int icase=1;icase<=ncase;icase++) { scanf("%d",&n); for(int i=0;i<n;i++) for(int j=0;j<n;j++) scanf("%d",&a[i][j]); int ans = INF; /*以下是我要借鉴的*/ for(int i=0;i<(1<<n);i++) /*数字位代表状态*/ ans=min(ans,Judge(i)); if(ans == INF)ans=-1; printf("Case %d: %d\n",icase,ans); } return 0; }
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int MAXN = 20; //const int INF = 0x3fffffff;999 const int INF = 99999; int n,a[MAXN][MAXN],b[MAXN][MAXN]; int Judge(int m) { //memset(b,0,sizeof(b)); int tmp=0; for(int i=0;i<n;i++) for(int j=0;j<n;j++) b[i][j]=a[i][j]; for(int i=0;i<n;i++) /**/ { if((m & (1<<i))) { if(0 == b[0][i]) { b[0][i]=1; /*有1表示do*/ tmp++; } else return INF; } } for(int i=1;i<n;i++) for(int j=0;j<n;j++) { int sum=0; if(j-1>=0)sum+=b[i-1][j-1]; if(j+1<n)sum+=b[i-1][j+1]; if(i-2>=0)sum+=b[i-2][j]; if(sum%2) { if(!b[i][j]) { b[i][j]=1; tmp++; } //else 这种情况太二逼了 我居然没发现这个bug // return INF; } else { if(b[i][j] == 1) return INF; } } // 这种写法是有问题的,因为 /*以上的步骤都没有检测最后一行,一下测试最后一行*/ for(int i=0;i<n;i++) { int sum=0; if(n-2>=0)sum+=b[n-2][i]; if(i>0)sum+=b[n-1][i-1]; if(i+1<n)sum+=b[n-1][i+1]; if(sum%2)return INF; } return tmp; } int main() { int ncase; scanf("%d",&ncase); //while(n--) for(int icase=1;icase<=ncase;icase++) { scanf("%d",&n); for(int i=0;i<n;i++) for(int j=0;j<n;j++) scanf("%d",&a[i][j]); int ans = INF; /*以下是我要借鉴的*/ for(int i=0;i<(1<<n);i++) /*数字位代表状态*/ ans=min(ans,Judge(i)); if(ans == INF)ans=-1;//printf("-1\n"); printf("Case %d: %d\n",icase,ans); } return 0; }