d780. NOIP2009 4.靶形数独@Morris' Blog|PChome Online 人新台
2011-08-16 12:06:47| 人1,053| 回0 | 上一篇 | 下一篇

d780. NOIP2009 4.靶形数独

0 收藏 0 0 站台

d780. NOIP2009 4.靶形数独

容 :

小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低。但普通的数独对他们来说都过于简单了,于是他们向 Z博士请教,Z 博士拿出了他最近发明的“靶形数独” ,作为这两个孩子比试的题目。 
     靶 形数独的方格同普通数独一样,在 9 格宽×9 格高的大九宫格中有 9 个 3 格宽×3 格高的小九宫格(用粗黑色线隔开的) 。在这个大九宫格中, 有一些数字是已知的,根据这些数字,利用逻辑推理,在其他的空格上填入 1到 9 的数字。每个数字在每个小九宫格内不能重复出现,每个数字在每行、每列 也不能重复出现。但靶形数独有一点和普通数独不同,即每一个方格都有一个分值,而且如同一个靶子一样,离中心越近则分值越高。 (如图)
    上图具体的分值分布是:最里面一格(黄色区域)为 10 分,黄色区域外面的一圈(红色区域)每个格子为 9 分,再外面一圈(蓝色区域)每个格子为 8分,蓝色区域外面一圈(棕色区域)每个格子为 7分,最外面一圈(白色区域)每个格子为 6 分,如上图所示。
     比赛的要求是:每个人必须完成一个给定的数独(每个给定数独可能有不同的填法) ,而且要争取更高的总分数。而这个总分数即每个方格上的分值和完成这个数独时填在相应格上的数字的乘积的总和。如图,在以下的这个已经填完数字的靶形数独游戏中,总分数为 2829。游戏规定,将以总分数的高低决出胜负。 
 
     由于求胜心切,小城找到了善于编程的你,让你帮他求出,对于给定的靶形数独,能够得到的最高分数。

入明 :

一共 9 行。每行 9 个整数(每个数都在 09 的范围内) ,表示一个尚未填满的数独方格,未填的空格用“0”表示。每两个数字之间用一个空格隔开。 

出明 :

输出可以得到的靶形数独的最高分数。如果这个数独无解,则输出整数-1。

例入 :help

7 0 0 9 0 0 0 0 1 1 0 0 0 0 5 9 0 0 0 0 0 2 0 0 0 8 0 0 0 5 0 2 0 0 0 3 0 0 0 0 0 0 6 4 8 4 1 3 0 0 0 0 0 0 0 0 7 0 0 2 0 9 0 2 0 1 0 6 0 8 0 4 0 8 0 5 0 4 0 1 2 

例出 :

2829 

提示 :

40%的数据,数独中非 0数的个数不少于 30。 
80%的数据,数独中非 0数的个数不少于 26。 
100%的数据,数独中非 0 数的个数不少于 24。 

//其实本题有20个点,每个点的时限为2s。
//由于zerojudge的时间限制最大只能是1s,所以我只把能够在1s内的测试数据提交,并且只提交了10个点。
//官方测试数据中,其实只有第17点和第20点很难在1s内通过,因此在此略去。
//其实是因为zerojudge的评测系统不够快,他们在一些更快的评测系统的OJ上是可以在1s内通过的!
//以下给出第17点的测试数据,供大家钻研到能在1s内通过:

Sample input:

0 0 0 9 0 0 0 0 0
7 0 0 2 0 0 0 0 0
5 2 0 8 0 0 0 0 0
6 0 0 7 0 2 0 3 4
2 0 0 0 0 0 0 0 7
3 7 4 0 0 0 0 0 5
9 0 2 4 1 0 0 7 0
0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 9 0 0

Sample output:

2856

 

出 :

NOIP2009提高组第四题 (管理:liouzhou_101)


作法 : Dancing Links

/**********************************************************************************/
/*  Problem: d780 "NOIP2009 4.靶形数独" from NOIP2009提高组第四题       */
/*  Language: C                                                                   */
/*  Result: AC (49ms, 293KB) on ZeroJudge                                         */
/*  Author: morris1028 at 2011-08-16 11:46:27                                     */
/**********************************************************************************/


#include<stdio.h>
#include<stdlib.h>
#define Maxv 100000
struct DacingLinks {
    int left, right;
    int up, down;
    int data, ch, rh;
}DL[100001 + 1001];
int s[1001], o[1001], head, size;
int n, m, a, b, c, tn, Ans;
int Score[10][10]={
                    {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},
                    };
void Remove(int c) {
    DL[DL[c].right].left = DL[c].left;
    DL[DL[c].left].right = DL[c].right;
    int i, j;
    for(i = DL[c].down; i != c; i = DL[i].down) {
        for(j = DL[i].right; j != i; j = DL[j].right) {
            DL[DL[j].down].up = DL[j].up;
            DL[DL[j].up].down = DL[j].down;
            s[DL[j].ch]--;
        }
    }
}
void Resume(int c) {
    int i, j;
    for(i = DL[c].down; i != c; i = DL[i].down) {
        for(j = DL[i].left; j != i; j = DL[j].left) {
            DL[DL[j].down].up = j;
            DL[DL[j].up].down = j;
            s[DL[j].ch]++;
        }
    }
    DL[DL[c].right].left = c;
    DL[DL[c].left].right = c;
}
void board(int k) {
    static int set[81], a, b;
    int sum = 0;
    for(a = 0; a < k; a++) {
        set[DL[o[a]].data] = DL[o[a]].rh+1;
    }
    for(a = 0; a < n; a++) {
        for(b = 0; b < n; b++) {
            sum += Score[a][b]*set[a*n+b];
        }
    }
    Ans = Ans > sum ? Ans : sum;
}
void DFS(int k) {
    if(DL[head].right == head) {
        board(k);
        return;
    }
    int t = Maxv, c, i, j;
    for(i = DL[head].right; i != head; i = DL[i].right) {
        if(s[i] < t) {
            t = s[i], c = i;
        }
    }
    Remove(c);
    for(i = DL[c].down; i != c; i = DL[i].down) {
        o[k] = i;
        for(j = DL[i].right; j != i; j = DL[j].right)
            Remove(DL[j].ch);
        DFS(k+1);
        for(j = DL[i].left; j != i; j = DL[j].left)
            Resume(DL[j].ch);
    }
    Resume(c);
}
int new_node(int up, int down, int left, int right) {
    DL[size].up = up, DL[size].down = down;
    DL[size].left = left, DL[size].right = right;
    DL[up].down = DL[down].up = DL[left].right = DL[right].left = size;
    return size++;
}
void new_row(int n, int Row[], int rh, int set) {
    int a, r, row = -1, k;
    for(a = 0; a < n; a++) {
        r = Row[a];
        DL[size].ch = r, DL[size].data = set, s[r]++;
        if(row == -1) {
            row = new_node(DL[DL[r].ch].up, DL[r].ch, size, size);
            DL[row].rh = rh;
        }else {
            k = new_node(DL[DL[r].ch].up, DL[r].ch, DL[row].left, row);
            DL[k].rh = rh;
        }
    }
}
void init(int m) {
    size = 0;
    head = new_node(0, 0, 0, 0);
    int i;
    for(i = 1; i <= m; i++) {
        new_node(i, i, DL[head].left, head);
        DL[i].ch = i, s[i] = 0;
    }
}
main() {
    int map[10][10], Row[10], t;
    n = 3;
    tn = n, n *= n, m = n*n*4, init(m);
    for(a = 0; a < n; a++)
        for(b = 0; b < n; b++) {
            scanf("%d", &map[a][b]);
            if(map[a][b] == 0) {
                for(c = 0; c < n; c++) {
                    t = 0;
                    Row[t++] = a*n + b + 1;
                    Row[t++] = n*n + a*n + c + 1;
                    Row[t++] = 2*n*n+ b*n + c + 1;
                    Row[t++] = 3*n*n+ (a/tn*tn + b/tn)*n + c + 1;
                    new_row(t, Row, c, a*n+b);
                }
            } else {
                c = map[a][b]-1, t = 0;
                Row[t++] = a*n + b + 1;
                Row[t++] = n*n + a*n + c + 1;
                Row[t++] = 2*n*n+ b*n + c + 1;
                Row[t++] = 3*n*n+ (a/tn*tn + b/tn)*n + c + 1;
                new_row(t, Row, c, a*n+b);
            }
        }
    Ans = 0, DFS(0);
    printf("%d\n", Ans);
    return 0;
}

台: Morris
人(1,053) | 回(0)| 推 (0)| 收藏 (0)|
全站分: 不分 | 人分: |
此分下一篇:d859. NOIP2001 1.数的计算
此分上一篇:b058. 3.

是 (若未登入"人新台"看不到回覆唷!)
* 入:
入片中算式的果(可能0) 
(有*必填)
TOP
全文
ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86