Flip Gamehtml
題意:和poj 1681同樣,4*4的01矩陣輸入爲b|w,關聯也是周圍四個方向。只是最優解(操做個數最少)是隻要最終同色就行,沒有肯定哪一個是1.ios
此題確實能夠直接枚舉第一行,ide
思路:本來認爲弄成自由變元的個數以後,所有變爲0和所有變爲1的操做數之和就是var - ret(自由變元的個數),這樣只須要調用Gauss一次便可。可是還有一個前提就是認爲最有解就是自由變元就認爲是沒操做,可是這一題與1681Painter's Problem 不一樣,必定要枚舉自由變元來肯定其餘維度的變量。因此仍是要兩次調用Gauss().spa
(Gauss-Jordan elimination):debug
#include<iostream> #include<cstdio> #include<cstring> #include<string.h> #include<algorithm> #include<map> #include<queue> #include<vector> #include<cmath> #include<stdlib.h> #include<time.h> using namespace std; #define rep0(i,l,r) for(int i = (l);i < (r);i++) #define rep1(i,l,r) for(int i = (l);i <= (r);i++) #define rep_0(i,r,l) for(int i = (r);i > (l);i--) #define rep_1(i,r,l) for(int i = (r);i >= (l);i--) #define MS0(a) memset(a,0,sizeof(a)) #define MS1(a) memset(a,-1,sizeof(a)) #define inf 0x3f3f3f3f int dir[2][4] = {{0,1,0,-1},{1,0,-1,0}}; int a[20][20]; int equ,var; int x[20],free_var[20]; void debug() { puts("********"); int i,j; rep0(i,0,equ){ rep1(j,0,var) cout<<a[i][j]<<" "; cout<<endl; }puts("********"); } int Gauss() { int i,j,k,row,col,cnt = 0; for(row = 0,col = 0;row < equ && col < var;row++,col++){ int mx = row; rep0(j,row+1,equ) if(abs(a[j][col]) > abs(a[mx][col])) mx = j; if(a[mx][col] == 0){ row--; // 行不變;不能經過這裏記錄自由變元的個數,只能記錄沒用的col free_var[cnt++] = col;//記錄自由變元的標號; continue; } if(mx != row) rep1(k,col,var) swap(a[row][k],a[mx][k]); rep0(j,row+1,equ){ if(a[j][col]){ rep1(k,col,var) a[j][k] ^= a[row][k]; } } } //debug(); rep0(i,row,equ) if(a[i][var] != 0) return -1; //無解 //枚舉自由變元,row表示有用的方程數方程,可是要在判斷出有解的前提下才能說有多組解; //if(row < var) return var - row; //當不須要枚舉時,直接返回自由變元的個數 int ans = inf,tot = 1 <<(var - row); rep0(i,0,tot){ int cnt = 0,tmp = i; rep0(j,0,var - row){ x[free_var[j]] = (tmp&1); if(x[free_var[j]]) cnt++;//** tmp >>= 1; } rep_1(i,row-1,0){ x[i] = a[i][var];//如今賦爲a[i][var],若爲自由變元以後仍是會等於0,不會重複計算; rep0(j,i+1,equ){ x[i] ^= (a[i][j] && x[j]); //第j個燈會影響到第i盞燈,同時第j盞燈也會亮 } if(x[i]) cnt++; } ans = min(ans,cnt); } return ans; } void init(int n) { MS0(x);MS0(a);MS0(free_var); int i,j,k; rep0(i,0,n) rep0(j,0,n){ int id = i*n+j; a[id][id] = 1; rep0(k,0,4){ int nx = i + dir[0][k] ,ny = j + dir[1][k]; if(nx < 0 || nx >= n || ny < 0 || ny >= n) continue; a[nx*n+ny][id] = 1; } } } int tmp[20]; int main() { //freopen("in.txt","r",stdin); //freopen("data2.txt","w",stdout); int n = 4,i,id = 0; equ = var = n*n; rep0(i,0,var){ char c = getchar(); if(c == 'w') id |= (1<<i);//使用狀壓來存儲狀態。 else if(c != 'b') i--; } init(n); rep0(i,0,var){ a[i][var] = (id >> i)& 1; } //debug(); int ans = inf; rep0(j,0,2){ int ret = Gauss(); if(ret == -1) continue; ans = min(ans,ret); if(j == 2) break; init(n); rep0(i,0,var){ a[i][var] = (id & 1)^1; id >>= 1; } } if(ans == inf) puts("Impossible"); else printf("%d\n",ans); return 0; }
dfs枚舉1:枚舉所有的格子狀態,即1<<16範圍;750ms..3d
#include<iostream> #include<cstdio> #include<cstring> #include<string.h> #include<algorithm> #include<map> #include<queue> #include<vector> #include<cmath> #include<stdlib.h> #include<time.h> using namespace std; #define rep0(i,l,r) for(int i = (l);i < (r);i++) #define rep1(i,l,r) for(int i = (l);i <= (r);i++) #define rep_0(i,r,l) for(int i = (r);i > (l);i--) #define rep_1(i,r,l) for(int i = (r);i >= (l);i--) #define MS0(a) memset(a,0,sizeof(a)) #define MS1(a) memset(a,-1,sizeof(a)) int dir[2][4] = {{0,1,0,-1},{1,0,-1,0}}; #define inf 0x3f3f3f3f int a[5][5],b[5][5]; int check(int s,int id) { int cnt = 0; rep0(i,0,4) rep0(j,0,4) b[i][j] = a[i][j]; rep0(i,0,16){ if(s&(1<<i)){ cnt++; int x = i/4,y = i % 4; b[x][y] ^= 1; rep0(j,0,4){ int nx = x + dir[0][j],ny = y + dir[1][j]; if(nx >= 0 && nx < 4 && ny >= 0 && ny < 4) b[nx][ny] ^= 1; } } } rep0(i,0,4) rep0(j,0,4) if(b[i][j] != id ) return inf; return cnt; } int solve(int id) { int i,j,tot = 1<<16,ans = inf; rep0(i,0,tot){ ans = min(ans,check(i,id)); } return ans; } int main() { //freopen("in.txt","r",stdin); //freopen("data2.txt","w",stdout); int n = 4; char c[5]; rep0(i,0,4){ scanf("%s",c); rep0(j,0,4) if(c[j] == 'w') a[i][j] = 1; else a[i][j] = 0; } int ans = inf; ans = min(ans,solve(0)); ans = min(ans,solve(1)); if(ans == inf) puts("Impossible"); else printf("%d\n",ans); return 0; }
dfs枚舉第一行:坑爹的WA了..要是看出bug,請評論..code
#include<iostream> #include<cstdio> #include<cstring> #include<string.h> #include<algorithm> #include<map> #include<queue> #include<vector> #include<cmath> #include<stdlib.h> #include<time.h> using namespace std; #define rep0(i,l,r) for(int i = (l);i < (r);i++) #define rep1(i,l,r) for(int i = (l);i <= (r);i++) #define rep_0(i,r,l) for(int i = (r);i > (l);i--) #define rep_1(i,r,l) for(int i = (r);i >= (l);i--) #define MS0(a) memset(a,0,sizeof(a)) #define MS1(a) memset(a,-1,sizeof(a)) int dir[2][4] = {{0,1,0,-1},{1,0,-1,0}}; #define inf 0x3f3f3f3f int a[5][5],b[5][5]; int check(int s,int id) { int cnt = 0; rep0(i,0,4) rep0(j,0,4) b[i][j] = a[i][j]; rep0(i,0,4){ if(s&(1<<i)){ cnt++; b[0][i] ^= 1; rep0(j,0,4){ int nx = 0 + dir[0][j],ny = i + dir[1][j]; if(nx >= 0 && nx < 4 && ny >= 0 && ny < 4) b[nx][ny] ^= 1; } } } rep0(i,1,3){ rep0(j,0,4)if(b[i-1][j] != id){ cnt++; b[i][j] ^= 1; rep0(k,0,4){ int nx = i + dir[0][k],ny = j + dir[1][k]; if(nx >= 0 && nx < 4 && ny >= 0 && ny < 4) b[nx][ny] ^= 1; } } } rep0(i,0,4) rep0(j,0,4) if(b[i][j] != id) return inf; return cnt; } int solve(int id) { int tot = 1<<4,ans = inf; rep0(i,0,tot){ ans = min(ans,check(i,id)); } return ans; } int main() { //freopen("in.txt","r",stdin); //freopen("data2.txt","w",stdout); char c[5]; rep0(i,0,4){ scanf("%s",c); rep0(j,0,4) if(c[j] == 'w') a[i][j] = 1; else a[i][j] = 0; } int ans = inf; ans = min(ans,solve(0)); ans = min(ans,solve(1)); if(ans == inf) puts("Impossible"); else printf("%d\n",ans); return 0; }