【noip2009】靶形数独(搜索+二进制优化)

来源:互联网 发布:80端口入侵教程 编辑:程序博客网 时间:2024/06/04 21:55

题意

    给出一张9*9的未填满的数独,以及每个网格的权值val。求Max{∑val[i][j]*a[i][j]},a[i][j]表示一张合法数独第i行j列上所填数字。

数据范围

    数独中非0数的个数不少于24

思路

    搜索+二进制优化
    按照一般填数独的策略,每次选择能够填的数最少的格子填。使用二进制表示行H,列L,块X上能够填的数,第i行j列处于k块的格子能填的数的二进制表示即为H[i]&L[j]&X[Loc[i][j]]。
    预处理出十进制2^p的p用于枚举可填的颜色。预处理1<<9种情况分别能够填的数的数量cnt,cnt[i] = cnt[i - lowbit(i)] + 1。
    lowbit(i)取i的二进制表示最右端的1所表示的十进制数。

Code

#include<cstdio>#include<cstring>#include<algorithm>#define lowbit(x) (x&(-x))const int Loc[9][9] = {{0,0,0,1,1,1,2,2,2},                       {0,0,0,1,1,1,2,2,2},                       {0,0,0,1,1,1,2,2,2},                       {3,3,3,4,4,4,5,5,5},                       {3,3,3,4,4,4,5,5,5},                       {3,3,3,4,4,4,5,5,5},                       {6,6,6,7,7,7,8,8,8},                       {6,6,6,7,7,7,8,8,8},                       {6,6,6,7,7,7,8,8,8}}; const int Val[9][9] = {{6,6,6,6,6,6,6,6,6},                       {6,7,7,7,7,7,7,7,6},                       {6,7,8,8,8,8,8,7,6},                       {6,7,8,9,9,9,8,7,6},                       {6,7,8,9,10,9,8,7,6},                       {6,7,8,9,9,9,8,7,6},                       {6,7,8,8,8,8,8,7,6},                       {6,7,7,7,7,7,7,7,6},                       {6,6,6,6,6,6,6,6,6}};int ans = -1;int yes[10];int H[10],L[10],X[10];int rep[1<<9],cnt[1<<9];int Init() {    for(int i = 0; i < 9; ++i) {        rep[1<<i] = i;        H[i] = L[i] = X[i] = (1<<9)-1;    }    for(int i = 1; i < (1<<9); ++i)        cnt[i] = cnt[i-lowbit(i)] + 1;    int val, ret = 0, t;    for(int i = 0; i < 9; ++i)        for(int j = 0; j < 9; ++j) {            scanf("%d",&val);            if(val) {                t = 1 << val-1;                H[i] ^= t;                L[j] ^= t;                X[Loc[i][j]] ^= t;                 ret += val * Val[i][j];            }            else yes[i] |= (1<<j);        }    return ret;}void Dfs(int sum) {    int t,j,tot,val,x,y,mn = 10;    for(int i = 0; i < 9; ++i) {        t = yes[i];        while(t) {            j = lowbit(t), t ^= j, j = rep[j];            tot = cnt[H[i]&L[j]&X[Loc[i][j]]];            if(tot < mn) {                mn = tot;                 x = i, y = j;            }        }    }    if(mn == 10) {        if(sum > ans) ans = sum;        return;    }    yes[x] ^= 1<<y;    t = H[x]&L[y]&X[Loc[x][y]];    while(t) {        val = lowbit(t), t ^= val;        H[x] ^= val, L[y] ^= val, X[Loc[x][y]] ^= val;        Dfs(sum + Val[x][y]*(rep[val]+1));        H[x] ^= val, L[y] ^= val, X[Loc[x][y]] ^= val;    }    yes[x] ^= 1<<y;}int main() {    Dfs(Init());    printf("%d\n",ans);    return 0;}
原创粉丝点击