zoukankan      html  css  js  c++  java
  • 飞行员兄弟

    飞行员兄弟

    给出一个(4 imes 4)的网格图,网格图上的数字由0,1组成,每次操作可以选择一个位置,让该个位置所在的一行上,一列上所有的数字1变为0,0变为1,给出一个初始局面,询问最少的操作让所有数字变为0。

    这是一道类异或问题,因此对于一个位置的重复操作是没有意义的,现在问题转化为对那些位置操作了。

    网格图问题,按行处理的话,注意到一个位置上的改变,引起了每一行的改变,于是无法剪枝,只有16个格子,(2^{16}=65536),不如直接暴力枚举。

    于是用二进制枚举,将网格图拆行成列,二进制上的每一位对应了网格图上的一个位置是否进行操作(至于怎么对应,按你自己习惯),但是为了快速变换,实现预处理出点击一个位置,会对哪些格子造成改变,直接二进制下的位运算就体现了点击这个位置局面的改变,随便事先统计好每个数二进制位下1的个数,这样就可以做到(O(2^{16} imes 16)=1048576)

    参考代码:

    #include <iostream>
    #include <cstdio>
    #define il inline
    #define ri register
    #define li 65536
    #define intmax 0x7fffffff
    using namespace std;
    int t[16],tot[li];
    il void get(char&);
    int main(){
    	for(int i(0),j,k,l;i<4;++i)
    		for(j=0;j<4;++j)
    			for(k=0;k<4;++k)
    				t[i*4+j]|=1<<k+i*4,
    					t[i*4+j]|=1<<j+k*4;
    	for(int i(0),j;i<li;++i)
    		for(j=15;j>=0;--j)
    			if(i>>j&1)++tot[i];
    	char c;int ans(intmax),gzy,s(0);
    	for(int i(0);i<16;++i)
    		get(c),s|=(c=='-'?0:1)<<i;
    	for(int i(0),j,k;i<li;++i){
    		if(tot[i]>=ans)continue;
    		for(j=15,k=s;j>=0;--j)
    			if(i>>j&1)k^=t[j];
    		if(!k)ans=tot[i],gzy=i;
    	}printf("%d
    ",ans);
    	for(int i(0);i<16;++i)
    		if(gzy>>i&1)
    			printf("%d %d
    ",i/4+1,i%4+1);
    	return 0;
    }
    il void get(char &c){
    	while(c=getchar(),c==' '||c=='
    '||c=='
    ');
    }
    
    
  • 相关阅读:
    java谜题
    Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' 的解决办
    考虑用静态工厂代替构造器
    Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' 的解决办
    100 个高质量的 XHTML/CSS 模板(上)
    登陆时的安全性
    Flex 开发架构(五): Mate-基于标签的框架
    NIO的基本概念及简单示例
    Flex与jsp的联系
    福布斯:Sun的六大失误
  • 原文地址:https://www.cnblogs.com/a1b3c7d9/p/11220804.html
Copyright © 2011-2022 走看看