zoukankan      html  css  js  c++  java
  • P3032 [USACO11NOV]二进制数独Binary Sudoku

    题目描述

    Farmer John's cows like to play an interesting variant of the popular game of "Sudoku". Their version involves a 9 x 9 grid of 3 x 3 subgrids, just like regular Sudoku. The cows' version, however, uses only binary digits:

    000 000 000

    001 000 100

    000 000 000

    000 110 000

    000 111 000

    000 000 000

    000 000 000

    000 000 000

    000 000 000

    The goal of binary Sudoku is to toggle as few bits as possible so that each of the nine rows, each of the nine columns, and each of the nine 3 x 3 subgrids has even parity (i.e., contains an even number of 1s). For the example above, a set of 3 toggles gives a valid solution:

    000 000 000

    001 000 100

    001 000 100

    000 110 000

    000 110 000

    000 000 000

    000 000 000

    000 000 000

    000 000 000

    Given the initial state of a binary Sudoku board, please help the cows determine the minimum number of toggles required to solve it.

    给出一个9*9的01矩阵,问最少修改几个数能使每行、每列以及每个九宫格中1的个数均为偶数。

    输入输出格式

    输入格式:

     

    * Lines 1..9: Each line contains a 9-digit binary string corresponding to one row of the initial game board.

     

    输出格式:

     

    * Line 1: The minimum number of toggles required to make every row, column, and subgrid have even parity.

     

    输入输出样例

    输入样例#1: 
    000000000 
    001000100 
    000000000 
    000110000 
    000111000 
    000000000 
    000000000 
    000000000 
    000000000 
    
    输出样例#1: 
    3 
    

    说明

    The Sudoku board in the sample input is the same as in the problem text above.

    Three toggles suffice to solve the puzzle.

    Solution:

      本题贼有意思。

      很容易想到整个棋盘最多只要$81$次翻转(即把每个棋子都翻转),但是显然实际上不用这么多次。

      那么我们直接$IDA*$,每个位置的棋子要么翻转要么不翻转,然后分别记录一下每行、每列、每个九宫格内的棋子个数,估价函数就是取三者中不满足偶数条件个数最多的个数(至少需要这么多次翻转才能使棋子变为偶数),然后剪枝就好了。

    代码:

    #include<bits/stdc++.h>
    #define il inline
    #define ll long long
    #define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
    #define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--)
    using namespace std;
    const int N=15;
    int mp[N][N],dep,tmp[N][N],squ[N],line[N],lit[N];
    bool vis[N][N];
    
    il void change(int x,int y){
        if(x<=3){
            if(y<=3)squ[1]^=1;
            else if(y<=6)squ[2]^=1;
            else squ[3]^=1;
            return;
        }
        else if(x<=6){
            if(y<=3)squ[4]^=1;
            else if(y<=6)squ[5]^=1;
            else squ[6]^=1;
            return;
        }
        else {
            if(y<=3)squ[7]^=1;
            else if(y<=6)squ[8]^=1;
            else squ[9]^=1;
            return;
        }
    }
    
    il void dfs(int tot,int lsx,int lsy){
        if(tot>dep||lsx==10)return;
        int px=0,py=0,ps=0;
        For(i,1,9) {
            if(line[i]&1)px++;
            if(lit[i]&1)py++;
            if(squ[i]&1)ps++;
        }
        if((!px)&&(!py)&&(!ps))cout<<tot-1,exit(0);
        if(tot+max(px,max(py,ps))>dep)return;
        lsy++;
        if(lsy>9)lsy=1,lsx++;
        tmp[lsx][lsy]^=1,line[lsx]^=1,lit[lsy]^=1,change(lsx,lsy);
        dfs(tot+1,lsx,lsy);
        tmp[lsx][lsy]^=1,line[lsx]^=1,lit[lsy]^=1,change(lsx,lsy);
        dfs(tot,lsx,lsy);
    }
    
    int main(){
        For(i,1,9) {
            For(j,1,9){
                 scanf("%1d",&tmp[i][j]);
                 if(tmp[i][j])line[i]^=1,lit[j]^=1,change(i,j);
             }
        }
        bool f=0;
        For(i,1,9) if((line[i]&1)||(lit[i]&1)||(squ[i]&1)){f=1;break;}
        if(!f)cout<<0;
        else while(1)dep++,dfs(1,1,0);
        return 0;
    }
  • 相关阅读:
    给力牛人
    设计模式
    微软真的要放弃Windows品牌吗?
    SQL2005 Express 自动安装之命令行
    SQL where之 in 在变量
    数据库求闭包,求最小函数依赖集,求候选码,判断模式分解是否为无损连接,3NF,BCNF
    别浪费了你的大内存[转]
    QQ空间免费养5级花和拥有人参果
    asp.net2 统一搜索引擎关键字编码[转]
    把网速提高4倍的方法和动画教程
  • 原文地址:https://www.cnblogs.com/five20/p/9298883.html
Copyright © 2011-2022 走看看