BZOJ 1770: [Usaco2009 Nov]lights 燈 [高斯消元XOR 搜索]
Posted Candy?
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 1770: [Usaco2009 Nov]lights 燈 [高斯消元XOR 搜索]相关的知识,希望对你有一定的参考价值。
题意:
经典灯问题,求最少次数
本题数据不水,必须要暴搜自由元的取值啦
想了好久
然而我看到网上的程序都没有用记录now的做法,那样做遇到自由元应该可能会丢解吧...?
我的做法是把自由元保存下来,枚举的时候只枚举自由元
但这样没法最优性剪枝了
于是枚举的时候还是从n到1枚举,到i时如果i是主元这时候i的值已经可以算出来了,这样就可以最优性剪枝了
但注意主元i你不能用i这个方程,而要保存pivot[i]为i用了哪个方程
然后一个伪贪心策略是自由元先搜0
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <bitset> using namespace std; const int N=40,INF=1e9; inline int read(){ char c=getchar();int x=0,f=1; while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();} while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();} return x*f; } int n,m,u,v; bitset<N> a[N]; int fe[N],now; void Gauss(){ now=1; for(int i=1;i<=n;i++){ int j=now;//printf("hi %d %d %d\n",i,now,a[now][i]==1); while(j<=n&&!a[j][i]) j++; if(j==n+1) {fe[++fe[0]]=i;continue;} if(j!=now) swap(a[now],a[j]); for(int j=1;j<=n;j++) if(j!=now&&a[j][i]) a[j]^=a[now]; now++; } } int main(){ freopen("in","r",stdin); n=read();m=read(); for(int i=1;i<=m;i++) u=read(),v=read(),a[u][v]=a[v][u]=1; for(int i=1;i<=n;i++) a[i][n+1]=a[i][i]=1; Gauss(); //for(int i=1;i<=n;i++) printf("a %d %d\n",i,a[i][n+1]==1); //for(int i=1;i<=fe[0];i++) printf("fe %d %d\n",i,fe[i]); int ans=0; for(int i=1;i<=now;i++) if(a[i][n+1]) ans++; printf("%d",ans); }
以上是关于BZOJ 1770: [Usaco2009 Nov]lights 燈 [高斯消元XOR 搜索]的主要内容,如果未能解决你的问题,请参考以下文章
bzoj 1770: [Usaco2009 Nov]lights 燈
bzoj 1770 [Usaco2009 Nov]lights 燈 meet in the middle
bzoj千题计划187:bzoj1770: [Usaco2009 Nov]lights 燈 (高斯消元解异或方程组+枚举自由元)