社区讨论
70求调,T了6个点
P1074[NOIP 2009 提高组] 靶形数独参与者 1已保存回复 0
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mhjo60vv
- 此快照首次捕获于
- 2025/11/04 05:45 4 个月前
- 此快照最后确认于
- 2025/11/04 05:45 4 个月前
CPP
#include<bits/stdc++.h>
using namespace std;
const int g[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},
},p[10][2]={{0,0},{1,1},{1,4},{1,7},{4,1},{4,4},{4,7},{7,1},{7,4},{7,7}};
int ans[10][10],score,use[10];//当前填的数独,当前最高分,当前使用了几次数字
vector<int>box[10];//box[i][j]表示第i宫第j个格子填了什么
struct cnt0{
int ind,total;//原先在第几行,0的数量
}cntzero[10];//统计每一行0的数量
bool cmp(cnt0 a,cnt0 b){return a.total<b.total;}
bool check(){
int result=0;
for(int i=1;i<=9;++i){
for(int j=1;j<=9;++j){
int d=10-max(abs(i-5),abs(j-5));
if(ans[i][j])result+=d*ans[i][j];
else result+=9*d;
}
}
if(result<=score)return 1;//最优性剪枝
for(int i=1;i<=9;++i)
if(use[i]>9)
return 1;
return 0;
}
int calc(){//统计分数
int result=0;
for(int i=1;i<=9;++i)
for(int j=1;j<=9;++j)
result+=(10-max(abs(i-5),abs(j-5)))*ans[i][j];
return result;
}
void dfs(int x,int y){
if(check())return;
/*
if((double)clock()/CLOCKS_PER_SEC>=0.997){
if(score)printf("%d\n",score);
else printf("-1\n");
exit(0);
}
*///这里是卡时代码,使用后会WA
if(x>9||y>9){
score=max(score,calc());
return;
}
int row=cntzero[x].ind;
if(ans[row][y]){
if(y==9)dfs(x+1,1);
else dfs(x,y+1);
return;
}
if(10-max(abs(row-5),abs(y-5))>3)
//把分值高的点的分数从大到小枚举
for(int i=1;i<=9;++i){
int tmp1=g[row][y],tmp2=(row-1)%3*3+(y-1)%3+1;
//表示第row行,第y列在tmp1宫的tmp2个格子
bool flag=0;
for(int j=1;j<=9;++j){
if(i==ans[row][j]&&y!=j){//行是否重复
flag=1;
break;
}
if(ans[j][y]==i&&j!=row){//列是否重复
flag=1;
break;
}
if(box[tmp1][j]==i&&j!=tmp2){//宫是否重复
flag=1;
break;
}
}
if(flag)continue;
ans[row][y]=i;
box[tmp1][tmp2]=i;
++use[i];
if(y==9)dfs(x+1,1);
else dfs(x,y+1);
box[tmp1][tmp2]=0;
ans[row][y]=0;
--use[i];
}
else
for(int i=9;i>=1;--i){
int tmp1=g[row][y],tmp2=(row-1)%3*3+(y-1)%3+1;
bool flag=0;
for(int j=1;j<=9;++j){
if(i==ans[row][j]&&y!=j){
flag=1;
break;
}
if(ans[j][y]==i&&j!=row){
flag=1;
break;
}
if(box[tmp1][j]==i&&j!=tmp2){
flag=1;
break;
}
}
if(flag)continue;
ans[row][y]=i;
box[tmp1][tmp2]=i;
++use[i];
if(y==9)dfs(x+1,1);
else dfs(x,y+1);
box[tmp1][tmp2]=0;
ans[row][y]=0;
--use[i];
}
}
int main(){
memset(cntzero,-1,sizeof(cntzero));
for(int i=1;i<=9;++i){
cntzero[i].total=0;
for(int j=1;j<=9;++j){
scanf("%d",&ans[i][j]);
box[g[i][j]].push_back(ans[i][j]);
++use[ans[i][j]];
cntzero[i].total+=(ans[i][j]==0);
//统计第i行0的数量
}
cntzero[i].ind=i;
}
sort(cntzero+1,cntzero+10,cmp);
//优先搜索0的数量较少的行
dfs(1,1);
if(score!=0)printf("%d",score);
else printf("-1");
}
回复
共 0 条回复,欢迎继续交流。
正在加载回复...