1. 程式人生 > >Noip2009靶形數獨

Noip2009靶形數獨

true 方法 說明 %d () pan clas span ***

題目描述

小城和小華都是熱愛數學的好學生,最近,他們不約而同地迷上了數獨遊戲,好勝的他

們想用數獨來一比高低。但普通的數獨對他們來說都過於簡單了,於是他們向 Z 博士請教,

Z 博士拿出了他最近發明的“靶形數獨”,作為這兩個孩子比試的題目。

靶形數獨的方格同普通數獨一樣,在 9 格寬×9 格高的大九宮格中有 9 個 3 格寬×3 格

高的小九宮格(用粗黑色線隔開的)。在這個大九宮格中,有一些數字是已知的,根據這些數字,利用邏輯推理,在其他的空格上填入 1 到 9 的數字。每個數字在每個小九宮格內不能

重復出現,每個數字在每行、每列也不能重復出現。但靶形數獨有一點和普通數獨不同,即

每一個方格都有一個分值,而且如同一個靶子一樣,離中心越近則分值越高。(如圖)

技術分享

上圖具體的分值分布是:最裏面一格(黃色區域)為 10 分,黃色區域外面的一圈(紅

色區域)每個格子為 9 分,再外面一圈(藍色區域)每個格子為 8 分,藍色區域外面一圈(棕

色區域)每個格子為 7 分,最外面一圈(白色區域)每個格子為 6 分,如上圖所示。比賽的

要求是:每個人必須完成一個給定的數獨(每個給定數獨可能有不同的填法),而且要爭取

更高的總分數。而這個總分數即每個方格上的分值和完成這個數獨時填在相應格上的數字

的乘積的總和

總分數即每個方格上的分值和完成這個數獨時填在相應格上的數字

的乘積的總和。如圖,在以下的這個已經填完數字的靶形數獨遊戲中,總分數為 2829。遊戲規定,將以總分數的高低決出勝負。

技術分享

由於求勝心切,小城找到了善於編程的你,讓你幫他求出,對於給定的靶形數獨,能

夠得到的最高分數。

輸入輸出格式

輸入格式:

一共 9 行。每行 9 個整數(每個數都在 0―9 的範圍內),表示一個尚未填滿的數獨方

格,未填的空格用“0”表示。每兩個數字之間用一個空格隔開。

輸出格式:

輸出文件 sudoku.out 共 1 行。

輸出可以得到的靶形數獨的最高分數。如果這個數獨無解,則輸出整數-1。

輸入輸出樣例

輸入樣例#1:
sudoku1
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

sudoku2
0 0 0 7 0 2 4 5 3 
9 0 0 0 0 8 0 0 0 
7 4 0 0 0 5 0 1 0 
1 9 5 0 8 0 0 0 0 
0 7 0 0 0 0 0 2 5 
0 3 0 5 7 9 1 0 8 
0 0 0 6 0 1 0 0 0 
0 6 0 9 0 0 0 0 1 
0 0 0 0 0 0 0 0 6
輸出樣例#1:
sudoku1
2829

sudoku2
2852

說明

【數據範圍】

40%的數據,數獨中非 0 數的個數不少於 30。

80%的數據,數獨中非 0 數的個數不少於 26。

100%的數據,數獨中非 0 數的個數不少於 24。

NOIP 2009 提高組 第四題

/*************************************************************************************************************************************/

解題方法:

正著搜會卡數據,所以采用倒著搜或者豎著搜的方式

然後嘗試寫了個啟發式搜索,但是由於估價不對,結果80分(不如正著暴力。。)

還是乖乖地按照順序搜吧

代碼:

#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;

int belong[9][9] = {
1,1,1,2,2,2,3,3,3,
1,1,1,2,2,2,3,3,3,
1,1,1,2,2,2,3,3,3,
4,4,4,5,5,5,6,6,6,
4,4,4,5,5,5,6,6,6,
4,4,4,5,5,5,6,6,6,
7,7,7,8,8,8,9,9,9,
7,7,7,8,8,8,9,9,9,
7,7,7,8,8,8,9,9,9
};

int ver[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 mp[9][9];
int ans = -1;

bool hangvis[9][10];
bool lievis[9][10];
bool kuaivis[9][10];


void dfs(int now,int as)
{
    if(now == 81)
    {
        ans = max(ans,as);
        return;
    }
    int x = now % 9;
    int y = 8 - now/ 9;
    if(mp[x][y])
    {
        dfs(now + 1,as);
        return;
    }
    for(int i = 1;i <= 9;i++)
    {
        if(!hangvis[x][i] && !lievis[y][i] && !kuaivis[belong[x][y]][i])
        {
            hangvis[x][i] = true;
            lievis[y][i] = true;
            kuaivis[belong[x][y]][i] = true;
            mp[x][y] = i;
            dfs(now + 1,as + ver[x][y] * i);
            mp[x][y] = 0;
            hangvis[x][i] = false;
            lievis[y][i] = false;
            kuaivis[belong[x][y]][i] = false;
        }
    }
    
    
}

int main()
{
    int op = 0; 
    for(int i = 0;i < 9;i++)
        for(int j = 0;j < 9;j++)
        {
            scanf("%d",&mp[i][j]);
            hangvis[i][mp[i][j]] = true;
            lievis[j][mp[i][j]] = true;
            kuaivis[belong[i][j]][mp[i][j]] = true;
            op += mp[i][j] * ver[i][j];
        }
    dfs(0,op);
    printf("%d",ans);
    return 0;
}

Noip2009靶形數獨