*PS:卡常什么的最讨厌了
因为题面太长所以并不想粘qwq
第一遍打的暴搜,codevs 上90,洛谷75,感觉自己萌萌的。
结果打完启发函数后,codevs上A了,洛谷上一直T掉一个点QAQ,优化了一晚上,还是T掉(而且这个点暴搜没T),最后放弃了… T _ T
方法就是每次都从可能性最小的点开始搜,记一下每行每列每宫里已经填了的数的种类,从种类最多的开始搜(也可以加上已经填了的数量)。同时记得打表(分数,宫也可以)。
当然你也可以考虑每次从0最少的地方开始搜,或者进行最优化剪枝(当前还没填的数的个数*90+当前得分<=ans return)、或者用inline、register或O2优化、加上位运算或手读、从9到1倒着枚举、能用char的用char…
暴搜
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int cnt,ans=-1,Sum;
int a[10][10],hang[10][10],lie[10][10],gong[10][10][10];
int ch[10],cl[10],cg[10][10];
struct maple{
int x,y,h;
}point[100];
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}};
bool cmp(maple a,maple b)
{
return a.h>b.h;
}
void Done_used(int i,int j,int k,int d,int d2)
{
hang[i][k]=lie[j][k]=gong[(i-1)/3][(j-1)/3][k]=d;
}
void Dfs(int k,int sum) //填到第k个数,总值为sum
{
if(k==cnt)
{
ans=max(ans,sum);
return ;
}
int x=point[k+1].x,y=point[k+1].y;
for(int i=1;i<=9;++i)
if(!hang[x][i]&&!lie[y][i]&&!gong[(x-1)/3][(y-1)/3][i])
{
Done_used(x,y,i,1,1);
Dfs(k+1,sum+i*score[x][y]);
Done_used(x,y,i,0,-1);
}
}
int main()
{
for(int i=1;i<=9;++i)
for(int j=1;j<=9;++j)
{
scanf("%d",&a[i][j]);
Done_used(i,j,a[i][j],1,1);
Sum+=a[i][j]*score[i][j];
}
for(int i=1;i<=9;++i)
for(int j=1;j<=9;++j)
if(!a[i][j])
point[++cnt]=(maple){i,j,0};
Dfs(0,Sum);
printf("%d",ans);
return 0;
}
codevs AC
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int cnt,ans=-1,Sum;
int a[10][10],hang[10][10],lie[10][10],gong[10][10][10];
struct maple{
int x,y;
}point[100];
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}};
void Done_used(int i,int j,int k,int d,int l,int r)
{
hang[i][k]=lie[j][k]=gong[l][r][k]=d;
}
int Done_data()
{
int sum=0,pos;
for(int i=1;i<=cnt;++i)
if(!a[point[i].x][point[i].y])
{
int k=0,l=(point[i].x-1)/3,r=(point[i].y-1)/3;
for(int j=1;j<=9;++j)
if(hang[point[i].x][j]||lie[point[i].y][j]||gong[l][r][j])
++k;
if(k>sum)
{
sum=k;
pos=i;
}
}
return pos;
}
void Dfs(int k,int sum) // 填到第k个数,总值为sum
{
if(k==cnt)
{
ans=max(ans,sum);
return ;
}
if(sum+(cnt-k)*90<=ans) return;
int j=Done_data();
int x=point[j].x,y=point[j].y;
int l=(x-1)/3,r=(y-1)/3;
for(int i=1;i<=9;++i)
if(!hang[x][i]&&!lie[y][i]&&!gong[l][r][i])
{
a[x][y]=i;
Done_used(x,y,i,1,l,r);
Dfs(k+1,sum+i*score[x][y]);
Done_used(x,y,i,0,l,r);
a[x][y]=0;
}
}
int main()
{
for(int i=1;i<=9;++i)
for(int j=1;j<=9;++j)
{
scanf("%d",&a[i][j]);
Sum+=a[i][j]*score[i][j];
if(!a[i][j]) point[++cnt]=(maple){i,j};
else Done_used(i,j,a[i][j],1,(i-1)/3,(j-1)/3);
}
Dfs(0,Sum);
printf("%d",ans);
return 0;
}