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,pivot[N];
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];
        pivot[i]=now;//printf("pivot %d\n",i);
        now++;
    }
}   
int val[N],tot,ans=INF;
void pri(){
    puts("free");
    for(int i=1;i<=fe[0];i++) printf("fe %d %d %d\n",i,fe[i],val[i]);
    puts("end");
}
int fir=1;
void dfs(int d){
    //printf("dfs %d %d\n",d,tot);
    if(tot>=ans) return;
    if(d==0) ans=min(ans,tot);//if(fir==1) printf("tot %d\n",tot),pri(),fir=0;}
    else if(pivot[d]){//printf("d %d\n",d);
        int i=pivot[d];
        int _=a[i][n+1];
        for(int j=1;j<=fe[0];j++)
            if(a[i][fe[j]]) _^=val[fe[j]];
        tot+=_;
        dfs(d-1);
        tot-=_;
    }else{
        val[d]=0;
        dfs(d-1);
        val[d]=1; tot++;
        dfs(d-1);
        tot--;
    }
}
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]);
    dfs(n);
    printf("%d",ans);
}

 

posted @ 2017-02-18 15:04  Candy?  阅读(540)  评论(0编辑  收藏  举报