题目链接
https://www.lydsy.com/JudgeOnline/problem.php?id=2003
题解
考虑搜索。
确定了第一行和第一列,那么就确定了整个矩阵,因此搜索的范围可以降到399个位置。
首先搜索第一行,显然每个不是第一行第一列的位置都可以由三个位置唯一确定:(1,1),(1,i),(j,1)(1,1),(1,i),(j,1)(1,1),(1,i),(j,1)。由于搜索的是第一行,可以把(i,j)(i,j)(i,j)这个位置=0=0=0和=p−1=p-1=p−1都带入一遍,得到的结果就是(j,1)(j,1)(j,1)的上下界。如果搜索的过程中发现冲突了那么说明第一行这样填不行,剪枝。
代码
#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;
}