首页 > 代码库 > BZOJ 1770: [Usaco2009 Nov]lights 燈 [高斯消元XOR 搜索]
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 搜索]
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。