zoukankan      html  css  js  c++  java
  • Kaka's Matrix Travels

    POJ

    洛咕

    给出一个(n*n)的矩阵,每一格有一个非负整数(A_{i,j},(A_{i,j} <= 1000)),现在从((1,1))出发,可以往右或者往下走,最后到达((n,n)),每达到一格,把该格子的数取出来,该格子的数就变成(0),这样一共走(K)次,现在要求(K)次所达到的方格的数的和最大.((1<=n<=50, 0<=k<=10).)

    分析:构建费用流模型(点边转化,拆点法).每个格子((i,j))对应一个节点((i-1)*n+j),拆成一个入点和一个出点,入点向出点连两条有向边,一条容量为1,费用为格子((i,j))中的数(表示第一次经过该点是把数取走);另一条容量(k-1),费用为(0)(表示之后再经过该点时,不能再取数了).((i,j))的出点还要向((i,j+1))((i+1,j))的入点连有向边,容量为(k),费用为(0)(怎么走都不会有取数).

    然后以((1,1))为源点,((n,n))为汇点,求最大费用最大流即可.

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #define ll long long
    using namespace std;
    inline int read(){
        int x=0,o=1;char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')o=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*o;
    }
    const int N=200005;//懒得想数组具体要开多大了
    int n,k,s,t,max_flow,ans;
    int dis[N],visit[N],pre[N],incf[N];
    int tot,head[N],nxt[N],to[N],limit[N],w[N];
    inline void add(int a,int b,int c,int d){
    	nxt[++tot]=head[a];head[a]=tot;
    	to[tot]=b;limit[tot]=c;w[tot]=d;
    	nxt[++tot]=head[b];head[b]=tot;
    	to[tot]=a;limit[tot]=0;w[tot]=-d;
    }
    inline bool spfa(){
    	for(int i=1;i<N;++i)dis[i]=-1e9,visit[i]=0;
    	queue<int>q;q.push(s);dis[s]=0;visit[s]=1;
    	incf[s]=1<<30;
    	while(q.size()){
    		int u=q.front();q.pop();visit[u]=0;
    		for(int i=head[u];i;i=nxt[i]){
    			if(!limit[i])continue;
    			int v=to[i];
    			if(dis[v]<dis[u]+w[i]){
    				dis[v]=dis[u]+w[i];
    				incf[v]=min(incf[u],limit[i]);
    				pre[v]=i;
    				if(!visit[v])visit[v]=1,q.push(v);
    			}
    		}
    	}
    	if(dis[t]==-1e9)return false;
    	return true;
    }
    inline void update(){
    	int x=t;
    	while(x!=s){
    		int i=pre[x];
    		limit[i]-=incf[t];
    		limit[i^1]+=incf[t];
    		x=to[i^1];
    	}
    	max_flow+=incf[t];
    	ans+=dis[t]*incf[t];
    }
    int main(){
    	n=read(),k=read();s=1;t=2*n*n;tot=1;
    	for(int i=1;i<=n;++i){
    		for(int j=1;j<=n;++j){
    			int val=read();
    			add((i-1)*n+j,(i-1)*n+j+n*n,1,val);
    			add((i-1)*n+j,(i-1)*n+j+n*n,k-1,0);
    			if(j+1<=n)add((i-1)*n+j+n*n,(i-1)*n+j+1,k,0);
    			if(i+1<=n)add((i-1)*n+j+n*n,i*n+j,k,0);
    		}
    	}
    	while(spfa())update();
    	printf("%d
    ",ans);
        return 0;
    }
    
    
  • 相关阅读:
    Java实现 蓝桥杯VIP 算法训练 字符串逆序
    Java实现 蓝桥杯VIP 算法训练 字符串逆序
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 成绩的等级输出
    Java实现 蓝桥杯VIP 算法训练 成绩的等级输出
    Qt 自定义model实现文件系统的文件名排序
  • 原文地址:https://www.cnblogs.com/PPXppx/p/11614185.html
Copyright © 2011-2022 走看看