前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【NOIP1999 提高组T4】 靶形数独

【NOIP1999 提高组T4】 靶形数独

作者头像
pai233
发布2022-01-12 15:06:19
2980
发布2022-01-12 15:06:19
举报
文章被收录于专栏:pai233的专栏pai233的专栏

一道挺水的DFS。

题目详情

小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低。但普通的数独对他们来说都过于简单了,于是他们向 ZZZ 博士请教,ZZZ 博士拿出了他最近发明的“靶形数独”,作为这两个孩子比试的题目。

靶形数独的方格同普通数独一样,在 9×99 \times 99×9 格高的大九宫格中有 999 个 3×33 \times 33×3 格高的小九宫格(用粗黑色线隔开的)。在这个大九宫格中,有一些数字是已知的,根据这些数字,利用逻辑推理,在其他的空格上填入 111 到 999 的数字。每个数字在每个小九宫格内不能重复出现,每个数字在每行、每列也不能重复出现。但靶形数独有一点和普通数独不同,即每一个方格都有一个分值,而且如同一个靶子一样,离中心越近则分值越高。(如图)

image.png
image.png

上图具体的分值分布是:最里面一格(黄色区域)为 101010 分,黄色区域外面的一圈(红色区域)每个格子为 999 分,再外面一圈(蓝色区域)每个格子为 888 分,蓝色区域外面一圈(棕色区域)每个格子为 777 分,最外面一圈(白色区域)每个格子为 666 分,如上图所示。比赛的要求是:每个人必须完成一个给定的数独(每个给定数独可能有不同的填法),而且要争取更高的总分数。而这个总分数即每个方格上的分值和完成这个数独时填在相应格上的数字的乘积的总和。如图,在以下的这个已经填完数字的靶形数独游戏中,总分数为 282928292829 。游戏规定,将以总分数的高低决出胜负。

image.png
image.png

由于求胜心切,小城找到了善于编程的你,让你帮他求出,对于给定的靶形数独,能够得到的最高分数。

做法

这道题爆搜肯定不行,所以要像平时做数独时一样,从 000 少的地方开始搜索。

代码

代码语言:javascript
复制
#include<bits/stdc++.h>
using namespace std;
struct countxy{
	int rank,sum;
}data[10];
int x[10][10],y[10][10],all[10][10],a[10][10],s[100][4];
int u,maxans=-1,nowscore;
int getpoint_DJX(int i,int j){
	if(i==1 or j==1 or i==9 or j==9)return 6;
	else if(i==2 or j==2 or i==8 or j==8)return 7;
	else if(i==3 or j==3 or i==7 or j==7)return 8;
	else if(i==4 or j==4 or i==6 or j==6)return 9;
	else return 10;
}
bool cmp(countxy a,countxy b){
	return a.sum<b.sum; 
}
int getpoint_xy(int i,int j){
	if(i<=3){
		if(j<=3)return 1;
		else if(j<=6)return 2;
		else return 3;
	}
	else if(i<=6){
		if(j<=3)return 4;
		else if(j<=6)return 5;
		else return 6;
	}
	else{
		if(j<=3)return 7;
		else if(j<=6)return 8;
		else return 9;
	}
}
void dfs(int p,int score){
	if(p==u){
		if(score>maxans)maxans=score;
		return;
	}
	for(int i=1;i<=9;i++){
		if(!x[s[p][0]][i] and !y[s[p][1]][i] and !all[s[p][3]][i]){
			x[s[p][0]][i]=y[s[p][1]][i]=all[s[p][3]][i]=1;
			dfs(p+1,score+(s[p][2]*i));
			x[s[p][0]][i]=y[s[p][1]][i]=all[s[p][3]][i]=0;
		}
	}
}
void Init(){
	freopen("sudoku.in","r",stdin);
	freopen("sudoku.out","w",stdout);
	for(int i=1;i<=9;i++){
		data[i].rank=i;
	}
}
void ReadData(){
	for(int i=1;i<=9;i++){
		for(int j=1;j<=9;j++){
			scanf("%d",&a[i][j]);
			if(a[i][j]>0){
				nowscore+=a[i][j]*getpoint_DJX(i,j);
				x[i][a[i][j]]=y[j][a[i][j]]=all[getpoint_xy(i,j)][a[i][j]]=1;
			}
			else data[i].sum++;
		}
	}
	sort(data+1,data+10,cmp);
}
void OutPutAns(){
	printf("%d",maxans);
}
void Work(){
	for(int i=1;i<=9;i++){
		for(int j=1;j<=9;j++){
			if(a[data[i].rank][j]==0){
				s[u][0]=data[i].rank,s[u][1]=j;
				s[u][2]=getpoint_DJX(data[i].rank,j);
				s[u++][3]=getpoint_xy(data[i].rank,j);
			}
		}
	}
}
void Search(){
	dfs(0,nowscore);
}
int main(){
	Init();
	ReadData();
	Work();
	Search();
	OutPutAns();
	return 0;
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-01-022,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 题目详情
  • 做法
  • 代码
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档