zoukankan      html  css  js  c++  java
  • [省选联考 2021 A 卷] 矩阵游戏

    前言

    缓慢填坑ing

    差分约束的题还是见少了,完全没思路。

    Acetyl orz

    题目

    洛谷

    讲解

    首先我们不考虑 (10^6) 这个限制,显然做法很多,比如强制 (a_{n,i}=a_{j,m}=0),然后递推一下就好了。

    然后调整解决问题。

    可以发现一行如果 (+r -r +r -r,...),并不会对 (b) 矩阵产生影响,同理,一列也没有影响,于是我们可以构造出这么一个矩阵表示调整值:

    [egin{pmatrix}&r_1+c_1 &-r_1+c_2 &r_1+c_3,&cdots\&r_2-c_1 &-r_2-c_2 &r_2-c_3,&cdots\&r_3+c_1 &-r_3+c_2 &r_3+c_3,&cdots\&vdots&vdots&vdots&ddots\end{pmatrix} ]

    但这个矩阵的形式并不好看,我们微调一下:

    [egin{pmatrix}&r_1-c_1 &c_2-r_1 &r_1-c_3,&cdots\&c_1-r_2 &r_2-c_2 &c_3-r_2,&cdots\&r_3-c_1 &c_2-r_3 &r_3-c_3,&cdots\&vdots&vdots&vdots&ddots\end{pmatrix} ]

    这样看上去就统一多了,然后直接套差分约束即可。

    具体的,上述矩阵为 (Delta_{i,j}=X-Y) 的形式,可以得到不等式 (0le a_{i,j}+Delta_{i,j}le 10^6),再转换一下变成 (-a_{i,j}le Delta_{i,j}le 10^6-a_{i,j}),连边即可。

    值得注意的是如果使用裸的SPFA判负环会TLE,你可使用上文提到的巨佬的deque优化写法,也可以使用洛谷上评测更快的stack写法。个人经验是如果用SPFA判负环,stack会快很多。

    虽然感觉时间复杂度很离谱,但是可以通过。

    代码

    代码不长,容易理解
    //12252024832524
    #include <bits/stdc++.h>
    #define TT template<typename T>
    using namespace std;
    
    typedef long long LL;
    const int MAXN = 305;
    const LL INF = 1ll << 60;
    int n,m;
    int a[MAXN][MAXN],b[MAXN][MAXN];
    bool inq[MAXN<<1];
    LL dis[MAXN<<1];
    
    LL Read()
    {
    	LL x = 0,f = 1; char c = getchar();
    	while(c > '9' || c < '0'){if(c == '-') f = -1;c = getchar();}
    	while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
    	return x * f;
    }
    TT void Put1(T x)
    {
    	if(x > 9) Put1(x/10);
    	putchar(x%10^48);
    }
    TT void Put(T x,char c = -1)
    {
    	if(x < 0) putchar('-'),x = -x;
    	Put1(x); if(c >= 0) putchar(c);
    }
    TT T Max(T x,T y){return x > y ? x : y;}
    TT T Min(T x,T y){return x < y ? x : y;}
    TT T Abs(T x){return x < 0 ? -x : x;}
    
    int head[MAXN<<1],tot,cnt[MAXN<<1];
    struct edge
    {
    	int v,w,nxt;
    }e[MAXN*MAXN*4];
    void Add_Edge(int x,int y,int z)
    {
    	e[++tot] = edge{y,z,head[x]};
    	head[x] = tot;
    }
    
    int main()
    {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	for(int T = Read(); T ;-- T)
    	{
    		n = Read(); m = Read();
    		for(int i = 1;i < n;++ i)
    			for(int j = 1;j < m;++ j)	
    				b[i][j] = Read();
    		for(int i = 1;i <= m;++ i) a[n][i] = 0;
    		for(int i = 1;i <= n;++ i) a[i][m] = 0;
    		for(int i = n-1;i >= 1;-- i)
    			for(int j = m-1;j >= 1;-- j)
    				a[i][j] = b[i][j] - a[i+1][j] - a[i][j+1] - a[i+1][j+1];
    		for(int i = 1;i <= n+m;++ i) head[i] = cnt[i] = 0,inq[i] = 0,dis[i] = INF; tot = 0;
    		for(int i = 1;i <= n;++ i)
    			for(int j = 1;j <= m;++ j)
    			{
    				int MIN = -a[i][j],MAX = 1000000-a[i][j];
    				if((i+j)&1) //c-r
    				{
    					Add_Edge(n+j,i,-MIN);
    					Add_Edge(i,n+j,MAX);
    				}
    				else //r-c
    				{
    					Add_Edge(i,n+j,-MIN);
    					Add_Edge(n+j,i,MAX);
    				}
    			}
    		stack<int> q; q.push(1); dis[1] = 0;
    		bool nonono = 0;
    		while(!q.empty())
    		{
    			int x = q.top(); q.pop(); inq[x] = 0;
    			for(int i = head[x],v; i && !nonono ;i = e[i].nxt)
    			{
    				v = e[i].v;
    				if(dis[x]+e[i].w < dis[v])
    				{
    					dis[v] = dis[x] + e[i].w;
    					if(!inq[v]) 
    					{
    						q.push(v);
    						++cnt[v];
    						if(cnt[v] > n+m) nonono = 1;
    						inq[v] = 1;
    					}
    				}
    			}
    		}
    		if(nonono) {printf("NO
    ");continue;}
    		printf("YES
    ");
    		for(int i = 1;i <= n;++ i,putchar('
    '))
    			for(int j = 1;j <= m;++ j)
    			{
    				if((i+j)&1) //c-r
    					Put(a[i][j]+dis[n+j]-dis[i],' ');
    				else 
    					Put(a[i][j]+dis[i]-dis[n+j],' ');
    			}
    	}
    	return 0;
    }
    
  • 相关阅读:
    委托与事件的关系
    分布式存储ceph——(1)部署ceph
    neutron二
    openstack第五章:cinder
    openstack第六章:dashboard
    openstack第一章:keystone
    openstack第二章:glance
    openstack第三章:nova
    openstack第四章:neutron— 网络服务
    openstack安装
  • 原文地址:https://www.cnblogs.com/PPLPPL/p/15467549.html
Copyright © 2011-2022 走看看