靶形数独 (dfs+预处理+状态压缩)
#2591. 「NOIP2009」靶形数独
【题目描述】
小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低。但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教, Z 博士拿出了他最近发明的“靶形数独”,作为这两个孩子比试的题目。
靶形数独的方格同普通数独一样,在 $9 格宽 \times9$ 格高 的大九宫格中有 $9$ 个 $3格宽\times3$ 格高 的小九宫格(用粗黑色线隔开的)。在这个大九宫格中,有一些数字是已知的,根据这些数字,利用逻辑推理,在其他的空格上填入 111 到 999 的数字。每个数字在每个小九宫格内不能 重复出现,每个数字在每行、每列也不能重复出现。但靶形数独有一点和普通数独不同,即 每一个方格都有一个分值,而且如同一个靶子一样,离中心越近则分值越高。(如图)
上图具体的分值分布是:里面一格(黄色区域)为 10 分,黄色区域外面的一圈(红色区域)每个格子为 9 分,再外面一圈(蓝色区域)每个格子为 8 分,蓝色区域外面一圈(棕色区域)每个格子为 7 分,外面一圈(白色区域)每个格子为 6 分,如上图所示。
比赛的要求是:每个人必须完成一个给定的数独(每个给定数独可能有不同的填法),而且要争取更高的总分数。而这个总分数即每个方格上的分值和完成这个数独时填在相应格上的数字的乘积的总和。
如图,在以下的这个已经填完数字的靶形数独游戏中,总分数为 2829 。游戏规定,将以总分数的高低决出胜负。
由于求胜心切,小城找到了善于编程的你,让你帮他求出,对于给定的靶形数独,能够得到的高分数。
【算法】
数独 Sudoku 基本一样。
【代码】
#include <bits/stdc++.h>
using namespace std;
int num,ans=-1,cur;
int G[10][10],rec[512],power[512];
int row[10],col[10],grid[10];
const int grade[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 g(int x,int y) {
return x/3*3+y/3;
}
void flip(int x,int y,int val) {
row[x]^=1<<(val-1);
col[y]^=1<<(val-1);
grid[g(x,y)]^=1<<(val-1);
}
void dfs(int now,int sum) {
if(sum+now*9*10<=ans) return;
if(now==0) {
ans=max(ans,sum);
return;
}
int minn=10,x,y;
for(int i=0;i<9;i++) {
for(int j=0;j<9;j++) {
if(G[i][j]) continue;
int val=row[i]&col[j]&grid[g(i,j)];
if(rec[val]<minn) minn=rec[val],x=i,y=j;
}
}
int val=row[x]&col[y]&grid[g(x,y)];
for(;val;val-=val&-val) {
int k=power[val&-val];
G[x][y]=k;
flip(x,y,k);
dfs(now-1,sum+k*grade[x][y]);
G[x][y]=0;
flip(x,y,k);
}
}
int main() {
for(int i=1;i<1<<9;i++)
for(int j=i;j;j-=j&-j)
rec[i]++;
for(int i=0;i<9;i++) {
row[i]=col[i]=grid[i]=(1<<9)-1;
power[1<<i]=i+1;
}
for(int i=0;i<9;i++) {
for(int j=0;j<9;j++) {
scanf("%d",&G[i][j]);
if(G[i][j]==0) num++;
else flip(i,j,G[i][j]),cur+=grade[i][j]*G[i][j];
}
}
dfs(num,cur);
printf("%d\n",ans);
return 0;
}
靶形数独 (dfs+预处理+状态压缩)的更多相关文章
- P1074 靶形数独 dfs+预处理
https://www.luogu.org/problemnew/show/P1074 显然是dfs 而且没有什么剪枝记忆化之类的 但是预处理比较麻烦 我用三个二维数组存状态:visx[x][i]代表 ...
- P1074 靶形数独 dfs回溯法
题目描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教,Z 博士拿出了他最近发明的“靶 ...
- codeforces B - Preparing Olympiad(dfs或者状态压缩枚举)
B. Preparing Olympiad You have n problems. You have estimated the difficulty of the i-th one as inte ...
- NOIP2009靶形数独[DFS 优化]
描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z博士请教,Z 博士拿出了他最近发明的“靶形数独 ...
- Preparing Olympiad---cf550B(DFS或者状态压缩模板)
比赛链接:http://codeforces.com/problemset/problem/550/B 给你n个数,选出来只是2个然后求他们的和在L和R的区间内,并且选出来的数中最大值和最小值的差不得 ...
- poj 3311 floyd+dfs或状态压缩dp 两种方法
Hie with the Pie Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 6436 Accepted: 3470 ...
- Light OJ 1037 - Agent 47(预处理状态压缩DP)
题目大意: 有个特工要执行任务,他会遭遇到最多15个目标,特工必须把他们全部杀死.当他杀死一个目标后他可以使用目标的武器来杀死其他人.因此他必须有一个杀人的顺序,使得他开枪的次数最小. 现在给你一个表 ...
- 预处理+状态压缩+剪枝——codefoece 1209E
那一步剪枝实在是没想到 #include<bits/stdc++.h> using namespace std; #define N 2005 struct Col{ ],Max[< ...
- poj 1753 Flip Game(bfs状态压缩 或 dfs枚举)
Description Flip game squares. One side of each piece is white and the other one is black and each p ...
随机推荐
- java:Conllection(List,set,get,map,subList)使用
list中的contains:是否包含指定元素 list中的SubList: 返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图. List<String ...
- 【NOIP2016提高A组8.12】奇袭
题目 由于各种原因,桐人现在被困在Under World(以下简称UW)中,而UW马上要迎来最终的压力测试--魔界入侵. 唯一一个神一般存在的Administrator被消灭了,靠原本的整合骑士的力量 ...
- [CF286C] Main Sequence
问题描述 定义幸运数列: 空数列是幸运数列 如果 S 是幸运数列,那么 {r, S, -r} 也是幸运数列 (r > 0) 如果 S 和 T 都是幸运数列,那么 {S, T} 也是幸运数列 给定 ...
- JavaScript正则表达式(四)
正则表达式方法 一.test方法 用于测试字符串参数中是否存在匹配正则表达式模式的字符串 如果存在就返回true,否则返回false 实例: 1.使用test方法不设置g标志时 2.使用test方法 ...
- JavaScript算数运算符和一元运算符
算数运算符 加法运算符(Addition): x + y 减法运算符(Subtraction): x - y 乘法运算符(Multiplication): x * y 除法运算符(Division): ...
- 判断img的src为空/点击时候两张图片来回替换
if($('.icon-right img').src==null){ $('.span-gray').addClass('c8'); } <img> ///////////// < ...
- 【bzoj3676】[Apio2014]回文串
*题目描述: 考虑一个只包含小写拉丁字母的字符串s.我们定义s的一个子串t的“出现值”为t在s中的出现次数乘以t的长度.请你求出s的所有回文子串中的最大出现值. *输入: 输入只有一行,为一个只包含小 ...
- 将HTML5封装成android应用APK文件若干方法(转)
HTML5拥有很多让人期待已久的新特性.HTML5的优势之一在于能够实现跨平台游戏编码移植,现在已经有很多公司在移动设备上使用HTML5技术.随着HTML5跨平台支持的不断增强和智能手机的 ...
- VMware 15 搭建MacOS 10.14教程
写于2018.12.23 教程原文链接:https://pan.baidu.com/s/1wvNYg_MQH_lwewKbpCQ5_Q ———————————————————————————————— ...
- spring MVC junit单元测试 各test之间共享变量
使用静态变量 private static String iPSetCode=null;