1. 程式人生 > >CODEVS 1174 靶形數獨

CODEVS 1174 靶形數獨

-1 博士 重復出現 sin 不能 font 都是 利用 put

題目描述 Description

小城和小華都是熱愛數學的好學生,最近,他們不約而同地迷上了數獨遊戲,好勝的他
們想用數獨來一比高低。但普通的數獨對他們來說都過於簡單了,於是他們向Z 博士請教,
Z 博士拿出了他最近發明的“靶形數獨”,作為這兩個孩子比試的題目。
靶形數獨的方格同普通數獨一樣,在 9 格寬×9 格高的大九宮格中有9 個3 格寬×3 格
高的小九宮格(用粗黑色線隔開的)。在這個大九宮格中,有一些數字是已知的,根據這些

數字,利用邏輯推理,在其他的空格上填入1 到9 的數字。每個數字在每個小九宮格內不能
重復出現,每個數字在每行、每列也不能重復出現。但靶形數獨有一點和普通數獨不同,即
每一個方格都有一個分值,而且如同一個靶子一樣,離中心越近則分值越高。

上圖具體的分值分布是:最裏面一格(黃色區域)為 10 分,黃色區域外面的一圈(紅
色區域)每個格子為9 分,再外面一圈(藍色區域)每個格子為8 分,藍色區域外面一圈(棕
色區域)每個格子為7 分,最外面一圈(白色區域)每個格子為6 分,如上圖所示。比賽的
要求是:每個人必須完成一個給定的數獨(每個給定數獨可能有不同的填法),而且要爭取
更高的總分數。而這個總分數即每個方格上的分值和完成這個數獨時填在相應格上的數字
的乘積的總和。如圖,在以下的這個已經填完數字的靶形數獨遊戲中,總分數為2829。遊
戲規定,將以總分數的高低決出勝負。

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


夠得到的最高分數。

技術分享 輸入描述 Input Description

一共 9 行。每行9 個整數(每個數都在0—9 的範圍內),表示一個尚未填滿的數獨方
格,未填的空格用“0”表示。每兩個數字之間用一個空格隔開。

輸出描述 Output Description

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

樣例輸入 Sample Input

【輸入輸出樣例 1】

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

【輸入輸出樣例 2】

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

樣例輸出 Sample Output

【輸入輸出樣例 1】

2829

【輸入輸出樣例 1】

2852

數據範圍及提示 Data Size & Hint

【數據範圍】
40%的數據,數獨中非0 數的個數不少於30。
80%的數據,數獨中非0 數的個數不少於26。
100%的數據,數獨中非0 數的個數不少於24。

題解:爆搜

記錄0的位置 只填0 卡時

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include<iostream>
using namespace std;

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

int value[10][10] = {{0},
    {0, 6, 6, 6, 6, 6, 6, 6, 6, 6},
    {0, 6, 7, 7, 7, 7, 7, 7, 7, 6},
    {0, 6, 7, 8, 8, 8, 8, 8, 7, 6},
    {0, 6, 7, 8, 9, 9, 9, 8, 7, 6},
    {0, 6, 7, 8, 9, 10,9, 8, 7 ,6},
    {0, 6, 7, 8, 9, 9, 9, 8, 7, 6},
    {0, 6, 7, 8, 8, 8, 8, 8, 7, 6},
    {0, 6, 7, 7, 7, 7, 7, 7, 7, 6},
    {0, 6, 6, 6, 6, 6, 6, 6, 6, 6}
};

int map[10][10];
int pos[101][2];       ////zeros
bool line[10][10], row[10][10], block[10][10];  //vis
int res = -1;
int times;

void dfs(int zeros, int sum)
{
    if(!zeros)
    {
        if(sum > res)res = sum;
        return;
    }
    if(times++ > 8000000)return;
    int i = pos[zeros][0], j = pos[zeros][1];
    for(int k = 1; k <= 9; k++)  //place number
    {
        if(!line[i][k] && !row[j][k] && !block[block_index[i][j]][k])
        {
            line[i][k] = row[j][k] = block[block_index[i][j]][k] = true;
            dfs(zeros - 1, sum + k * value[i][j]);
            line[i][k] = row[j][k] = block[block_index[i][j]][k] = false;
        }
    }
}

int main()
{
    int tot = 0;
    int zeros = 0;
    for(int i = 1; i <= 9; i++)
    {
        for(int j = 1; j < 10; j++)
        {
            int vvv;
            scanf("%d", &vvv);
            if(map[i][j] = vvv)
            {
                line[i][vvv] = row[j][vvv] = block[block_index[i][j]][vvv] = 1;
                tot += vvv * value[i][j];
            }else
            {
                zeros++;
                pos[zeros][0] = i;
                pos[zeros][1] = j;
            }
        }
    }
    dfs(zeros, tot);
    printf("%d\n", res? res: -1);
    return 0;
}

挨個填..洛谷只能95分,codevs上A了,因為codevs的時限是4s...洛谷1s....

#include<iostream>
#include<cstdio>
#include<ctime>
#include<cstring>
#include<algorithm>
using namespace std;
int cnt,ans,map[10][10],row[10][10],col[10][10],cub[10][10];
int score[10][10]={
0,0,0,0,0,0,0,0,0,0,
0,6,6,6,6,6,6,6,6,6,
0,6,7,7,7,7,7,7,7,6,
0,6,7,8,8,8,8,8,7,6,
0,6,7,8,9,9,9,8,7,6,
0,6,7,8,9,10,9,8,7,6,
0,6,7,8,9,9,9,8,7,6,
0,6,7,8,8,8,8,8,7,6,
0,6,7,7,7,7,7,7,7,6,
0,6,6,6,6,6,6,6,6,6
},
bel[10][10]={
0,0,0,0,0,0,0,0,0,0,
0,1,1,1,2,2,2,3,3,3,
0,1,1,1,2,2,2,3,3,3,
0,1,1,1,2,2,2,3,3,3,
0,4,4,4,5,5,5,6,6,6,
0,4,4,4,5,5,5,6,6,6,
0,4,4,4,5,5,5,6,6,6,
0,7,7,7,8,8,8,9,9,9,
0,7,7,7,8,8,8,9,9,9,
0,7,7,7,8,8,8,9,9,9
};

inline int read(){
    char ch=getchar();int x=0,f=1;
    for(;!isdigit(ch);ch=getchar())if(ch==-)f=-1;
    for(;isdigit(ch);ch=getchar())x=x*10+ch-0;
    return x*f;
}

void dfs(int x,int y,int sum){
    if(x==0){
        if(sum>ans)ans=sum;
        return;
    }
    if(map[x][y]){
        if(y==1)dfs(x-1,9,sum+map[x][y]*score[x][y]);
        else dfs(x,y-1,sum+map[x][y]*score[x][y]);
    }
    for(register int i=1;i<=9;i++){
        if(row[x][i]==0&&col[y][i]==0&&cub[bel[x][y]][i]==0){
            row[x][i]=col[y][i]=cub[bel[x][y]][i]=true;
            int cnt=sum+score[x][y]*i;
            if(y==1)dfs(x-1,9,cnt);
            else dfs(x,y-1,cnt);
            row[x][i]=col[y][i]=cub[bel[x][y]][i]=false;
        }
    }
}

int main(){
    for(register int i=1;i<=9;i++){
        for(int j=1;j<=9;j++){
           int x;
            x=read();
            map[i][j]=x;
            if(x){
                row[i][x]=true;
                col[j][x]=true;
                cub[bel[i][j]][x]=true;
            }
        }
    }
    ans=-1;
    dfs(9,9,0);
    if(ans<0)printf("-1\n");
    else printf("%d\n",ans);
    return 0;
}

CODEVS 1174 靶形數獨