金宣宗镇楼
简要说一下题面:
有一个鬼畜的数独,有九个宫(不是皇宫!!) ,九行和九列。保证每一个宫里没有重复的嫔妃 数字,每一行每一列也是如此。与正常数独不同的是,这个鬼畜的数独是有分数的,由于分数的分布像一个靶子,所以我们管它叫“靶形数独”。
每个格子的分数是格子中的数字与该格子的分数的乘积。现给出一个尚未填完的数独,求可能的最大分数。
以下是我的思考过程
乍一看,感觉这题非常恶心,就先从暴力的角度来思考:
因为数独已经给出来了,而且它是9x9不变的,所以可以考虑暴力搜索没有填数的格子,将其填上可能填写的数字。判断重复的话,for枚举一下就行了(逃
搜索思路嘛……就从(1,1)开始上下左右的搜,如果是空格就填,不是空格就继续上下左右......预计广搜实现。
所以理论时间复杂度是@¥¥&&¥@……&#%¥ 不太会算
反正掰指头算算,肯定是会T掉的,现在考虑优化。
从原来的暴力思路里面挑挑毛病,可以显而易见地发现判重的bug实在是大:总时间复杂度上面还要再乘一个9,谁都不会愿意的@_@
优化方案:搞三个布尔数组
\(row[i][j]\):第i行有没有j
\(line[i][j]\):第i列有没有j
\(gong[i][j]\):第i个宫有没有j
输入数独的时候更新一下即可。
同时维护一个队列存储空格子的坐标及所在宫,方便很多,也可以用dfs解决问题。
这时候发现好像似乎大概应该能卡过,但是直觉告诉我有可能卡不过(后来测了一次试试,75),于是找到一个优化:
以样例1为例:
7 0 0 9 0 0 0 0 1 //6个0
1 0 0 0 0 5 9 0 0 //6个0
0 0 0 2 0 0 0 8 0 //7个0
0 0 5 0 2 0 0 0 3 //6个0
0 0 0 0 0 0 6 4 8 //6个0
4 1 3 0 0 0 0 0 0 //6个0
0 0 7 0 0 2 0 9 0 //6个0
2 0 1 0 6 0 8 0 4 //4个0
0 8 0 5 0 4 0 1 2 //4个0
众所周知,搜索越到后面,剩余的格子可以填的数字方案就越少,所以刚开始尽量选择空格子少的行开始搜。考虑建立一个结构体数组,存入每一行的编号及空格子数量并进行排序,优先操作空格子少的行,于是在运行的时候又可以省下来一笔时间。
其实印象中这题应该要剪一堆的枝,用到一堆高深的搜索方法,结果把这个思路实现了之后交上去,竟然就过了……
就是这样。
code:
#include<bits/stdc++.h>
using namespace std;
int point[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};
int num[10][10],dark=0,maxans=-1,q[1010][4],dt=0;
bool gong[10][10],row[10][10],line[10][10];
struct data{
int zero,no;
}cnt[10];
bool cmp(data a,data b){
return a.zero<b.zero;
}
int g(int x,int y){
if(x<=3){
if(y<=3)return 1;
if(y>=7)return 3;
else return 2;
}
if(x>=7){
if(y<=3)return 7;
if(y>=7)return 9;
else return 8;
}
else{
if(y<=3)return 4;
if(y>=7)return 6;
else return 5;
}//返回宫编号
}
void read(){
for(register int i=1;i<=9;i++){
for(register int j=1;j<=9;j++){
cin>>num[i][j];
}
}//读入
}
void dfs(int ddt,int score){
if(ddt==dt+1){
maxans=max(score,maxans);
return ;
}
for(register int i=1;i<=9;i++){
if(!gong[q[ddt][3]][i]&&!line[q[ddt][2]][i]&&!row[q[ddt][1]][i]){
gong[q[ddt][3]][i]=line[q[ddt][2]][i]=row[q[ddt][1]][i]=1;
num[q[ddt][1]][q[ddt][2]]=i;
dfs(ddt+1,score+i*point[q[ddt][1]][q[ddt][2]]);
gong[q[ddt][3]][i]=line[q[ddt][2]][i]=row[q[ddt][1]][i]=0;
num[q[ddt][1]][q[ddt][2]]=0;
}
}
}
void doing(){
read();
for(register int i=1;i<=9;i++){
cnt[i].no=i;
for(register int j=1;j<=9;j++){
if(!num[i][j]){
cnt[i].zero++;
}
else{
row[i][num[i][j]]=1;
line[j][num[i][j]]=1;
gong[g(i,j)][num[i][j]]=1;
dark+=num[i][j]*point[i][j];
}
}
}
sort(cnt+1,cnt+10,cmp);
for(register int i=1;i<=9;i++){
for(register int j=1;j<=9;j++){
if(!num[cnt[i].no][j]){
q[++dt][1]=cnt[i].no;
q[dt][2]=j;
q[dt][3]=g(cnt[i].no,j);
}
}
}
dfs(1,dark);
}
int main(){
doing();
cout<<maxans;
}
~~92行,水得一批&_&~~