AcWing95 費解的開關 (遞推)
阿新 • • 發佈:2020-11-01
題目連結:https://www.acwing.com/problem/content/description/97/
有幾個重要性質:
- 每個位置最多被點選一次
- 若第一行狀態固定,那麼滿足題目要求的點選方案最多隻有一種
- 點選的先後順序不影響最終結果
於是將每行的狀態用二進位制數儲存,列舉第一行的點選狀態,然後向下遞推
題目問的是能否\(6\)步以內完成,要注意讀題。。
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<cmath> #include<stack> #include<queue> using namespace std; typedef long long ll; const int maxn = 10; int n; int a[maxn],b[maxn]; char s[maxn]; int t[maxn]; void print(int w){ memset(t,0,sizeof(t)); int cnt = 0; while(w){ t[++cnt] = w & 1; w >>= 1; } for(int i=5;i>=1;--i) printf("%d",t[i]); printf("\n"); } bool check(int x){ for(int i=0;i<5;++i){ if(!((x>>i) & 1)) return false; } return true; } int solve(int S){ memset(b,0,sizeof(b)); for(int i=1;i<=5;++i) b[i] = a[i]; int cnt = 0; for(int i=0;i<5;++i){ if((S>>i) & 1){ ++cnt; b[1] ^= (1<<i); b[2] ^= (1<<i); b[1] ^= (1<<(i+1)); b[1] ^= (1<<(i-1)); } } for(int i=2;i<=5;++i){ for(int j=0;j<5;++j){ if(!((b[i-1]>>j) & 1)){ ++cnt; b[i-1] ^= (1<<j); b[i] ^= (1<<j); b[i+1] ^= (1<<j); b[i] ^= (1<<(j+1)); b[i] ^= (1<<(j-1)); } } } if(check(b[5])) return cnt; else return -1; } ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; } int main(){ n = read(); while(n--){ for(int i=1;i<=5;++i) a[i] = 0; for(int i=1;i<=5;++i){ scanf("%s",s); for(int j=0;j<5;++j){ a[i] = (a[i] << 1) + s[j] - '0'; } } int ans = 1000000007, flag = 0; for(int S=0;S<(1<<5);++S){ int res = solve(S); if(res != -1){ flag = 1; ans = min(ans, res); } } if(!flag || ans > 6){ printf("-1\n"); }else{ printf("%d\n",ans); } } return 0; }