zoukankan      html  css  js  c++  java
  • bzoj1770: [Usaco2009 Nov]lights 灯

    传送门:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1770

    思路:繁体字是什么鬼啊....

    不过总比英语好...

    高斯消元解异或方程组。

    把每个灯开关次数看成变量,很显然只会是0和1

    然后对于每个灯建立方程,即它和与它相邻的灯的开关次数的异或和为1

    但是方程不一定只有唯一解,还会有自由元,就是取什么都会有解。

    所以最后还要枚举自由元暴搜

    (感觉复杂度会被卡,似乎折半搜更靠谱...不过还好没卡我)

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    const int maxn=40;
    using namespace std;
    int n,m,a[maxn][maxn],ans[maxn],tot,mins=10000;
    
    void gauss(){
    	for (int i=1;i<=n;i++){
    		int j=i;
    		for (;j<=n&&!a[j][i];j++);
    		if (j>n) continue;
    		if (i!=j) for (int k=1;k<=n+1;k++) swap(a[i][k],a[j][k]);
    		for (int j=1;j<=n;j++)
    			if (i!=j&&a[j][i])
    				for (int k=1;k<=n+1;k++)
    					a[j][k]^=a[i][k];
    	}
    }
    
    void dfs(int x){
    	if (tot>=mins) return;
    	if (!x){mins=min(mins,tot);return;}
    	if (a[x][x]){
    		int t=a[x][n+1];
    		for (int i=x+1;i<=n;i++) if (a[x][i]) t^=ans[i];
    		ans[x]=t;
    		if (t) tot++;
    		dfs(x-1);
    		if (t) tot--;  
    	}
    	else{
    		ans[x]=1,tot++,dfs(x-1),tot--;
    		ans[x]=0,dfs(x-1);
    	}
    }
    
    int main(){
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++) a[i][i]=a[i][n+1]=1;
    	for (int i=1,x,y;i<=m;i++) scanf("%d%d",&x,&y),a[x][y]=a[y][x]=1;
    	gauss(),dfs(n);printf("%d
    ",mins);
    	return 0;
    }


  • 相关阅读:
    pylint
    Cygwin安装与配置
    Spring的配置文件
    网络传输测试软件
    MINA快速传输文件
    Jar包下载
    shutdown彻底关闭tomcat,以及多线程关闭
    Git使用
    例说数学学习中的四基
    求等差数列前n项和S_n的最值
  • 原文地址:https://www.cnblogs.com/thythy/p/5493558.html
Copyright © 2011-2022 走看看