• hihoCoder 1196 高斯消元·二


    Description

    一个黑白网格,点一次会改变这个以及与其连通的其他方格的颜色,求最少点击次数使得所有全部变成黑色.

    Sol

    高斯消元解异或方程组.

    先建立一个方程组.

    (x_i) 表示这个点是否被用过.

    因为第二次使用同一个点,这个点的贡献就被消除了,所以每个点只会被用 0/1 次.

    (a_{ij}) 表示 (j) 点对 (i) 是否有影响,有影响为 1 否则为 0.

    最后的一位表示最后的状态^最初的状态.

    这样就列出来了 (n*m) 个方程组,一共 (n*m) 个未知数.

    然后求解,就跟高斯消元一样,用异或的方式消掉就可以了.

    Code

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    
    #define H(i,j) ((i-1)*m+j)
    const int N = 35;
    
    int n,m;
    int a[N][N];
    
    void print(){
    	cout<<"----------------------------"<<endl;
    	for(int i=1;i<=30;i++){
    		for(int j=1;j<=31;j++) cout<<a[i][j];
    		cout<<endl;
    	}
    }
    
    void init(){
    	n=5,m=6;
    	for(int i=1;i<=n;i++){
    		char s[N];memset(s,0,sizeof(s));
    		scanf("%s",s+1);
    		for(int j=1;j<=m;j++) a[H(i,j)][n*m+1]=1^(s[j]-'0');
    //		cout<<a[H(i,j)][n*m+1];
    //		cout<<endl<<s+1<<endl<<endl;
    	}
    	
    	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) {
    		a[H(i,j)][H(i,j)]=1;
    		if(i+1<=n) a[H(i,j)][H(i+1,j)]=1;
    		if(i-1>=1) a[H(i,j)][H(i-1,j)]=1;
    		if(j+1<=m) a[H(i,j)][H(i,j+1)]=1;
    		if(j-1>=1) a[H(i,j)][H(i,j-1)]=1;
    	}
    //	print();
    }
    
    void gauss(int n){
    	for(int i=1,r,j;i<n;i++){
    		for(r=j=i;j<n;j++) if(a[j][i]) { r=j;break; }
    //		cout<<i<<" "<<r<<endl;
    		if(r!=i) for(int k=i;k<=n;k++) swap(a[i][k],a[r][k]);
    		for(int k=i+1;k<n;k++) if(a[k][i]) {
    			for(j=i;j<=n;j++) a[k][j]^=a[i][j];
    		}
    //		print();
    	}
    //	print();
    	for(int i=n-1;i;i--){
    		for(int j=i+1;j<n;j++) a[i][n]^=a[j][n]*a[i][j];
    	}
    	
    }
    
    void out(){
    	int ans=0;
    	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(a[H(i,j)][n*m+1]) ans++;
    	cout<<ans<<endl;
    	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(a[H(i,j)][n*m+1]) cout<<i<<" "<<j<<endl;
    }
    
    int main(){
    //	freopen("in.in","r",stdin);
    //	freopen("log.out","w",stdout);
    	init();
    	gauss(31);
    	out();
    	
    	return 0;
    }
    

      

  • 相关阅读:
    android SQLite使用
    蓝牙从搜索到成功配对的全过程
    vscode 开发.net core 从安装到部署 教程详解
    ServiceStack 简单服务搭建
    MongoDB 安装配置
    request.url 端口 错误
    Python 之 hello world
    .NET DateTime 源码学习
    Parallel.For 平行算法 使用
    Thread.Join 和 Task.Wait 方法
  • 原文地址:https://www.cnblogs.com/beiyuoi/p/6115268.html
Copyright © 2020-2023  润新知