[loj3500]矩阵游戏

为了方便,令$a_{i,j}$的下标范围为$[0,n]$和$[0,m]$,$b_{i,j}$的下标范围为$[1,n]$和$[1,m]$

当确定$a_{i,0}$和$a_{0,j}$后,即可通过$b_{i,j}$来确定$a_{i,j}$,具体的有
$$
a_{i,j}=(-1)^{i+j}sum_{1le xle i,1le yle j}(-1)^{x+y}b_{x,y}+(-1)^{j}a_{i,0}+(-1)^{i}a_{0,j}-(-1)^{i+j}a_{0,0}
$$
由于在$i=0$或$j=0$时其也满足该式子,因此现在的条件变为:构造任意整数$a_{i,0}$和$a_{0,j}$,使得对于任意$i$和$j$(符合下标范围),上述式子计算得到后的结果在$[0,V]$中(其中$V=10^{6}$)

提出$(-1)^{i+j}$,再令$B_{i,j}=sum_{1le xle i,1le yle j}(-1)^{x+y}b_{x,y}$,即有
$$
a_{i,j}=(-1)^{i+j}(B_{i,j}+(-1)^{i}a_{i,0}+(-1)^{j}a_{0,j}-a_{0,0})
$$
令$x_{i}=(-1)^{i}a_{i,0}-a_{0,0}$和$y_{i}=(-1)^{i+1}a_{0,i}$,即$a_{i,j}=(-1)^{i+j}(B_{i,j}+x_{i}-y_{j})$

同时,条件考虑对$i+j$奇偶性分类讨论,即:

1.若$i+j$为偶数,则$-B_{i,j}le x_{i}-y_{j}le V-B_{i,j}$

2.若$i+j$为奇数,则$B_{i,j}le y_{j}-x_{i}le V+B_{i,j}$

对$x_{i}$和$y_{i}$这$n+m+2$个变量求差分约束即可,具体来说令$d_{i}$表示第$i$个变量的值,限制都可以转换为$d_{i}le d_{j}+x$,那么连边$(i,j,x)$后求最短路即满足此性质

由于有负权,需要spfa,最坏时间复杂度为$o(T(n+m)^{3})$

求出$x_{i}$和$y_{i}$后,即有$a_{i,j}=(-1)^{i+j}(B_{i,j}+x_{i}-y_{j})$,输出即可

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 605
 4 #define V 1000000
 5 #define ll long long
 6 struct Edge{
 7     int nex,to;
 8     ll len;
 9 }edge[N*N];
10 queue<int>q;
11 int E,t,n,m,head[N],vis[N],sum[N];
12 ll d[N],b[N][N];
13 void add(int x,int y,ll z){
14     edge[E].nex=head[x];
15     edge[E].to=y;
16     edge[E].len=z;
17     head[x]=E++;
18 }
19 bool spfa(){
20     memset(d,0x3f,sizeof(d));
21     memset(vis,0,sizeof(vis));
22     memset(sum,0,sizeof(sum));
23     d[0]=0;
24     q.push(0);
25     vis[0]=1;
26     while (!q.empty()){
27         int k=q.front();
28         q.pop();
29         for(int i=head[k];i!=-1;i=edge[i].nex)
30             if (d[edge[i].to]>d[k]+edge[i].len){
31                 d[edge[i].to]=d[k]+edge[i].len;
32                 if (!vis[edge[i].to]){
33                     q.push(edge[i].to);
34                     vis[edge[i].to]=1;
35                 }
36                 if (++sum[edge[i].to]>n+m)return 0;
37             }
38         vis[k]=0;
39     }
40     return 1;
41 }
42 int main(){
43     scanf("%d",&t);
44     while (t--){
45         scanf("%d%d",&n,&m);
46         n--,m--;
47         E=0;
48         memset(head,-1,sizeof(head));
49         for(int i=1;i<=n;i++)
50             for(int j=1;j<=m;j++){
51                 scanf("%lld",&b[i][j]);
52                 if ((i+j)&1)b[i][j]*=-1;
53                 b[i][j]+=b[i-1][j]+b[i][j-1]-b[i-1][j-1];
54             }
55         for(int i=0;i<=n;i++)
56             for(int j=0;j<=m;j++)
57                 if ((i+j)&1){
58                     add(i,j+n+1,V+b[i][j]);
59                     add(j+n+1,i,-b[i][j]);
60                 }
61                 else{
62                     add(j+n+1,i,V-b[i][j]);
63                     add(i,j+n+1,b[i][j]);
64                 }
65         if (!spfa()){
66             printf("NO
");
67             continue;
68         }
69         printf("YES
");
70         for(int i=0;i<=n;i++){
71             for(int j=0;j<=m;j++)
72                 if ((i+j)&1)printf("%lld ",d[j+n+1]-d[i]-b[i][j]);
73                 else printf("%lld ",b[i][j]+d[i]-d[j+n+1]);
74             printf("
");
75         }
76     }
77 }
View Code
原文地址:https://www.cnblogs.com/PYWBKTDA/p/14666585.html