转载注明出处: http://blog.csdn.net/u011400953
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 3979 | Accepted: 1564 |
Description
Input
Output
Sample Input
0 0 1 1 1 0 0 1 1 0 1 1 0 0 0 0 0 0 0 0
Sample Output
3
Hint
Source
【题目大意】:
奶牛有20只碗摆成一排,用鼻子顶某只碗的话,包括左右两只在内的一共三只碗会反向,现在给出碗的初始状态,问至少要用鼻子顶多少次才能使所有碗都朝上。
【分析】:
解亦或方程组的高斯消元法
【代码】:
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<algorithm> #include<iostream> #include<vector> #include<stack> #include<queue> using namespace std; #define MAXN 22 #define IMAX 21474836 int N,a[MAXN],ratio[MAXN][MAXN+1],ans[MAXN],ansreal=IMAX; void pre_mat() { for(int i=1;i<=N;i++) { if(i!=1) ratio[i][i-1]=1; if(i!=N) ratio[i][i+1]=1; ratio[i][i]=1; } } void swap_mat(int A,int B) { for(int i=1;i<=N+1;i++) swap(ratio[A][i],ratio[B][i]); } void guess(int now) { if(now==N+1) return; for(int i=now+1;i<=N;i++) if(ratio[i][now] && !ratio[now][now]) { swap_mat(now,i); break; } for(int i=now+1;i<=N;i++) if(ratio[i][now]) for(int j=now;j<=N+1;j++) ratio[i][j]^=ratio[now][j]; guess(now+1); } void solve(int now) { if(now==0) { int ansnow=0; for(int i=1;i<=N;i++) ansnow+=ans[i]; ansreal=min(ansreal,ansnow); return; } if(!ratio[now][now]) { for(int i=0;i<=1;i++) { ans[now]=i; for(int j=N;j>now;j--) ans[now]^=ratio[now][j]*ans[j]; solve(now-1); } } else { ans[now]=ratio[now][N+1]; for(int j=N;j>now;j--) ans[now]^=ratio[now][j]*ans[j]; solve(now-1); } } int main() { //freopen("input.in","r",stdin); //freopen("output.out","w",stdout); N=20; for(int i=1;i<=N;i++) { scanf("%d",&a[i]); ratio[i][N+1]=a[i]; } pre_mat(); guess(1); solve(N); printf("%d\n",ansreal); //system("pause"); return 0; }