要登录才能看题目:题目传送门
题目大意:
1、在数独的基础上,加入每行每列求和的条件;
上代码:
//caioj1044 简单数迷
//题解:深搜+剪枝
#include<cstdio>
#include<cstring>
int hs[20],ls[20],fx[20][20],fy[20][20];
int a[20][20],b[20][20];
int n,m,ans;
void dfs(int x,int y)
{
if(ans>1) return ;
if(x>n)//全图搜完了,有答案
{
for(int i=1;i<=m;i++)//必须每列都刚好
{
if(ls[i]!=0) return ;
}
ans++;
if(ans==1)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
b[i][j]=a[i][j];
}
}
}
return ;
}
if(y>m&&hs[x]==0) { dfs(x+1,1); return ; }//搜完一行了
if(a[x][y]!=0) { dfs(x,y+1); return; }//不用填
for(int i=1;i<=9;i++)//需要填
{
if(hs[x]-i>=0&&ls[y]-i>=0&&
fx[x][i]==0&&fy[y][i]==0)
{
hs[x]-=i; ls[y]-=i;
fx[x][i]=1;fy[y][i]=1;
a[x][y]=i;
dfs(x,y+1);
hs[x]+=i; ls[y]+=i;
fx[x][i]=0;fy[y][i]=0;
a[x][y]=0;
}
}
}
int main()
{
int t; scanf("%d",&t);
while(t--){
scanf("%d %d",&n,&m);
ans=0;
memset(fx,0,sizeof(fx));
memset(fy,0,sizeof(fy));
for(int i=1;i<=n;i++) scanf("%d",&hs[i]);
for(int i=1;i<=m;i++) scanf("%d",&ls[i]);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%d",&a[i][j]);
hs[i]-=a[i][j];
ls[j]-=a[i][j];
fx[i][a[i][j]]=1;
fy[j][a[i][j]]=1;
}
}
dfs(1,1);
if(ans==1)
for(int i=1;i<=n;i++)
{
for(int j=1;j<m;j++)
{
printf("%d ",b[i][j]);
}
printf("%d\n",b[i][m]);
}
if(ans==0) printf("No answer.\n");
if(ans>1) printf("Not unique.\n");
}
return 0;
}