zoukankan      html  css  js  c++  java
  • 洛谷 P7515 [省选联考 2021 A 卷] 矩阵游戏(构造,差分约束)

    传送门


    解题思路

    其实这个题部分分还是很好想的,但是考场上硬是没拿满…………
    直接说正解:
    假如没有对元素大小的限制,很显然可以直接设定第n行和第m列的数字为0,一定能构造出一组解。
    然后考虑限制。
    我们发现,对某一行或者某一列的元素进行(+1 -1 +1 -1 +1 -1 cdotscdots)对答案是没有影响的
    所以对于每一个点(i,j),就需要保证一个不等式的成立:
    (0leqslant b[i][j]pm h[i]pm l[j]leqslant 10^6)
    便于差分约束系统,我们对于行这样:
    (egin{vmatrix} +1 & -1 & +1 & -1 \ -1 & +1 & -1 & +1 \ +1 & -1 & +1 & -1 \ -1 & +1 & -1 & +1 \ end{vmatrix})
    对于列这样:
    (egin{vmatrix} -1 & +1 & -1 & +1 \ +1 & -1 & +1 & -1 \ -1 & +1 & -1 & +1 \ +1 & -1 & +1 & -1 \ end{vmatrix})
    于是式子就分成了i+j为偶数和奇数两种情况。
    最后连边跑一边差分约束即可。

    AC代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<queue>
    using namespace std;
    const int maxn=605;
    const int maxx=1000000;
    int n,m,T,p[maxn],dis[maxn],cnt,vis[maxn],times[maxn],a[305][305],b[305][305];
    struct node{
    	int v,next,w;
    }e[305*305*2];
    void insert(int u,int v,int w){
    	cnt++;
    	e[cnt].v=v;
    	e[cnt].w=w;
    	e[cnt].next=p[u];
    	p[u]=cnt;
    }
    queue<int> q;
    bool spfa(){
    	while(!q.empty()) q.pop();
    	memset(dis,0x3f,sizeof(dis));
    	dis[0]=0;
    	q.push(0);
    	vis[0]=1;
    	while(!q.empty()){
    		int u=q.front();
    		q.pop();
    		vis[u]=0;
    		for(int i=p[u];i!=-1;i=e[i].next){
    			int v=e[i].v;
    			if(dis[v]>dis[u]+e[i].w){
    				times[u]++;
    				if(times[u]>n+m) return false;
    				dis[v]=dis[u]+e[i].w;
    				if(!vis[v]){
    					vis[v]=1;
    					q.push(v);
    				}
    			}
    		}
    	}
    	return true;
    }
    int main(){
    	scanf("%d",&T); 
    	while(T--){
    		cnt=0;
    		memset(b,0,sizeof(b));
    		memset(times,0,sizeof(times));
    		memset(vis,0,sizeof(vis));
    		memset(p,-1,sizeof(p));
    		scanf("%d%d",&n,&m);
    		for(int i=1;i<=n+m;i++){
    			insert(0,i,0);
    		}
    		for(int i=1;i<n;i++){
    			for(int j=1;j<m;j++){
    				scanf("%d",&a[i][j]);
    			}
    		}
    		for(int i=n-1;i>=1;i--){
    			for(int j=m-1;j>=1;j--){
    				b[i][j]=a[i][j]-b[i+1][j]-b[i][j+1]-b[i+1][j+1];
    			}
    		}
    		for(int i=1;i<=n;i++){
    			for(int j=1;j<=m;j++){
    				if((i+j)%2==0){
    					insert(i,j+n,b[i][j]);
    					insert(j+n,i,maxx-b[i][j]);
    				}else{
    					insert(j+n,i,b[i][j]);
    					insert(i,j+n,maxx-b[i][j]);
    				}
    			}
    		}
    		if(spfa()){
    			printf("YES
    ");
    			for(int i=1;i<=n;i++){
    				for(int j=1;j<=m;j++){
    					if((i+j)%2==0){
    						printf("%d ",b[i][j]+dis[i]-dis[n+j]);
    					}else{
    						printf("%d ",b[i][j]-dis[i]+dis[n+j]);
    					}
    				}
    				printf("
    ");
    			}
    		}else{
    			printf("NO
    ");
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    MySQL百万级、千万级数据多表关联SQL语句调优
    不就是SELECT COUNT语句吗,居然有这么多学问
    分布式锁讲解
    Java 中堆和栈的区别
    Java中的回调机制
    在Eclipse上Maven环境配置使用
    项目忽然出现 The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path 解决方法
    HttpServletResponse
    com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after connection closed.
    深入浅出java常量池
  • 原文地址:https://www.cnblogs.com/yinyuqin/p/14788060.html
Copyright © 2011-2022 走看看