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;
    }
  • 相关阅读:
    后台架构设计—数据存储层
    Linux应用程序基础
    Linux文件管理命令笔记
    CentOS7搭建LAMP实战
    (ospf、rip、isis、EIGRP)常见的动态路由协议简介
    python while 循环语句
    获取linux帮助命令
    破解linux虚拟机的密码
    gawk编程语言
    MySQL触发器在PHP项目中用来做信息备份、恢复和清空的方法介绍
  • 原文地址:https://www.cnblogs.com/five20/p/9298883.html
Copyright © 2011-2022 走看看