版权声明:本文为博主原创文章,未经博主允许可以转载,但要注明出处 https://blog.csdn.net/wang3312362136/article/details/83091887
题目链接
https://www.lydsy.com/JudgeOnline/problem.php?id=2003
题解
考虑搜索。
确定了第一行和第一列,那么就确定了整个矩阵,因此搜索的范围可以降到399个位置。
首先搜索第一行,显然每个不是第一行第一列的位置都可以由三个位置唯一确定: 。由于搜索的是第一行,可以把 这个位置 和 都带入一遍,得到的结果就是 的上下界。如果搜索的过程中发现冲突了那么说明第一行这样填不行,剪枝。
代码
#include <cstdio>
#include <algorithm>
int read()
{
int x=0,f=1;
char ch=getchar();
while((ch<'0')||(ch>'9'))
{
if(ch=='-')
{
f=-f;
}
ch=getchar();
}
while((ch>='0')&&(ch<='9'))
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
const int maxn=200;
int n,m,p,a[maxn+10][maxn+10],l[maxn+10][maxn+10],r[maxn+10][maxn+10];
int f(int x)
{
return (x&1)?1:-1;
}
int search(int y)
{
if(y>m)
{
return 1;
}
for(a[1][y]=0; a[1][y]<p; ++a[1][y])
{
int flag=1;
for(int i=2; i<=n; ++i)
{
int b=(0-a[1][1]*f(i+y)-a[1][y]*f(i)-a[i][y])*f(y),c=((p-1)-a[1][1]*f(i+y)-a[1][y]*f(i)-a[i][y])*f(y);
if(b>c)
{
std::swap(b,c);
}
l[y][i]=std::max(l[y-1][i],b);
r[y][i]=std::min(r[y-1][i],c);
if(l[y][i]>r[y][i])
{
flag=0;
break;
}
}
if(flag)
{
if(search(y+1))
{
return 1;
}
}
}
return 0;
}
int main()
{
n=read();
m=read();
p=read();
for(int i=1; i<=n; ++i)
{
for(int j=1; j<=m; ++j)
{
a[i][j]=read();
}
}
for(int i=2; i<=n; ++i)
{
for(int j=2; j<=m; ++j)
{
a[i][j]-=a[i-1][j]+a[i][j-1]+a[i-1][j-1];
}
}
for(int i=2; i<=n; ++i)
{
l[1][i]=0;
r[1][i]=p-1;
}
for(a[1][1]=0; a[1][1]<p; ++a[1][1])
{
if(search(2))
{
for(int i=1; i<=n; ++i)
{
for(int j=1; j<=m; ++j)
{
if(i==1)
{
printf("%d%c",a[i][j],(j==m)?'\n':' ');
}
else if(j==1)
{
printf("%d%c",l[m][i],(j==m)?'\n':' ');
}
else
{
printf("%d%c",a[i][j]+a[1][1]*f(i+j)+a[1][j]*f(i)+l[m][i]*f(j),(j==m)?'\n':' ');
}
}
}
return 0;
}
}
return 0;
}