题目链接:http://poj.org/problem?id=3185
题意:20盏灯排成一排。操作第i盏灯的时候,i-1和i+1盏灯的状态均会改变。给定初始状态,问最少操作多少盏灯使得所有灯的状态最后均为0.
思路:高斯消元,记录变元个数,枚举变元。
int a[N][N],ans[N];
vector<int> b;
int Gauss()
{
b.clear();
int i,j=1,k,t;
for(i=1;i<=20;i++)
{
for(k=j;k<=20;k++) if(a[k][i]) break;
if(k>20)
{
b.pb(i);
continue;
}
for(t=1;t<=21;t++) swap(a[k][t],a[j][t]);
for(t=1;t<=20;t++) if(t!=j&&a[t][i])
{
for(k=1;k<=21;k++) a[t][k]^=a[j][k];
}
j++;
}
for(i=j;i<=20;i++) if(a[i][21]) return -1;
if(j<=20) return 21-j;
for(i=1;i<=20;i++) ans[i]=a[i][21];
return 0;
}
int main()
{
int num=0;
int i;
FOR1(i,20)
{
RD(a[i][21]);
a[i][i]=1;
if(i>1) a[i-1][i]=1;
if(i<20) a[i+1][i]=1;
}
int t=Gauss();
if(t==0)
{
int sum=0;
FOR1(i,20) sum+=ans[i];
PR(sum);
return 0;
}
int sum=INF,st,j,k;
FOR0(st,(1<<t))
{
FOR0(i,t) ans[b[i]]=(st>>i)&1;
for(i=20-t;i>=1;i--)
{
for(j=i;j<=20;j++) if(a[i][j]) break;
ans[j]=a[i][21];
for(k=j+1;k<=20;k++) if(a[i][k]) ans[j]^=ans[k];
}
int temp=0;
FOR1(i,20) temp+=ans[i];
upMin(sum,temp);
}
PR(sum);
}