HOJ 2715 Matrix3

news/2024/10/29 3:32:27/

限制增广次数的费用流。

【题目大意】

一个N*N的网格,每个单元都有一个价值Vi的宝物和一个高度Hi。现在ZhouGuyue要作至多K次旅行,每次旅行如下:他可以借助bin3的直升机飞到任意一个单元,之后他每次只能向相邻的且高度比当前所在格子低的格子移动。当他移动到一个边界的格子上时,他可以跳出这个网格并完成一次旅行。旅行中所到之处的宝物他可以全部拿走,一旦拿走原来的格子里就没有宝物了。问他最多能拿走价值多少的宝物。(1 <= N <= 50, 0 <= K <= 50, 0 <= Vi <= 10000)  
【建模方法】 
将每个格子i拆成两个点i’, i’’并加边(i’, i’’, 1, -Vi), (i’, i’’, ∞, 0), (s, i’, ∞, 0);对相邻的四个格子j,若Hi > Hj则加边(i’’, j’, ∞, 0);若格子i在边界上则加边(i’’, t, ∞, 0)。限制增广次数小于等于K求最小费用流即可。

以上摘自Edelweiss《网络流建模汇总》

启示:

1.增广次数做了限制的问题还是比较好解决的,对每次增广后用计数器次数统计就可以了。

2.这里要求费用尽量大,可以把所有费用赋为-value,然后做费用流,得到结果的相反数就是最大的费用。

3.有的边,当第一次经过它时,可获利cost,以后经过便不再获利,则加两天边(u,v,1,-cost),(u,v,INF,0)。其实就是每种情况都对应一条边。同时,由最短路的性质,当前节点u一定会选择一条边权尽量小的边线走,因此可以保证第一次经过时的获利。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <queue>
  6 #define maxn 5010
  7 #define maxm 100000
  8 #define INF 1<<30
  9 using namespace std;
 10 
 11 int N,K;
 12 struct MCMF{
 13     int src,sink,e,n;
 14     int first[maxn];
 15     int cap[maxm],cost[maxm],v[maxm],next[maxm];
 16     bool flag;
 17     void init(){
 18         e = 0;
 19         memset(first,-1,sizeof(first));
 20     }
 21 
 22     void add_edge(int a,int b,int cc,int ww){
 23         //printf("add:%d to %d,cap = %d,cost = %d\n",a,b,cc,ww);
 24         cap[e] = cc;cost[e] = ww;v[e] = b;
 25         next[e] = first[a];first[a] = e++;
 26         cap[e] = 0;cost[e] = -ww;v[e] = a;
 27         next[e] = first[b];first[b] = e++;
 28     }
 29 
 30     int d[maxn],pre[maxn],pos[maxn];
 31     bool vis[maxn];
 32 
 33     bool spfa(int s,int t){
 34         memset(pre,-1,sizeof(pre));
 35         memset(vis,0,sizeof(vis));
 36         queue<int> Q;
 37         for(int i = 0;i <= n;i++)   d[i] = INF;
 38         Q.push(s);pre[s] = s;d[s] = 0;vis[s] = 1;
 39         while(!Q.empty()){
 40             int u = Q.front();Q.pop();
 41             vis[u] = 0;
 42             for(int i = first[u];i != -1;i = next[i]){
 43                 if(cap[i] > 0 && d[u] + cost[i] < d[v[i]]){
 44                     d[v[i]] = d[u] + cost[i];
 45                     pre[v[i]] = u;pos[v[i]] = i;
 46                     if(!vis[v[i]])  vis[v[i]] = 1,Q.push(v[i]);
 47                 }
 48             }
 49         }
 50         return pre[t] != -1;
 51     }
 52 
 53     int Mincost;
 54     int Maxflow;
 55 
 56     int MinCostFlow(int s,int t,int nn){
 57         Mincost = 0,Maxflow = 0,n = nn;
 58         int cnt = 0;
 59         while(spfa(s,t)){
 60             cnt++;
 61             if(cnt > K) break;
 62             int min_f = INF;
 63             for(int i = t;i != s;i = pre[i])
 64                 if(cap[pos[i]] < min_f) min_f = cap[pos[i]];
 65             Mincost += d[t] * min_f;
 66             Maxflow += min_f;
 67             for(int i = t;i != s;i = pre[i]){
 68                 cap[pos[i]] -= min_f;
 69                 cap[pos[i]^1] += min_f;
 70             }
 71         }
 72         return Mincost;
 73     }
 74 };
 75 
 76 MCMF g;
 77 int value[55][55],h[55][55];
 78 
 79 inline int id(int i,int j){
 80     return i*N + j;
 81 }
 82 
 83 int dx[] = {0,1,0,-1};
 84 int dy[] = {1,0,-1,0};
 85 int main(){
 86     int kase;
 87     scanf("%d",&kase);
 88     while(kase--){
 89         g.init();
 90         scanf("%d%d",&N,&K);
 91         for(int i = 0;i < N;i++)
 92             for(int j = 0;j < N;j++)
 93                 scanf("%d",&value[i][j]);
 94         for(int i = 0;i < N;i++)
 95             for(int j = 0;j < N;j++)
 96                 scanf("%d",&h[i][j]);
 97         int S = N*N*2,T = S+1;
 98         for(int i = 0;i < N;i++){
 99             for(int j = 0;j < N;j++){
100                 g.add_edge(S,id(i,j),INF,0);
101                 g.add_edge(id(i,j),id(i,j)+N*N,1,-value[i][j]);
102                 g.add_edge(id(i,j),id(i,j)+N*N,INF,0);
103                 for(int k = 0;k < 4;k++){
104                     int x = i + dx[k];
105                     int y = j + dy[k];
106                     if(x < 0 || x >= N || y < 0 || y >= N)  continue;
107                     if(h[i][j] <= h[x][y])  continue;
108                     g.add_edge(id(i,j)+N*N,id(x,y),INF,0);
109                 }
110                 if(i == 0 || i == N-1 || j == 0 || j == N-1){
111                     g.add_edge(id(i,j)+N*N,T,INF,0);
112                 }
113             }
114         }
115         //printf("OK\n");
116         int ans = g.MinCostFlow(S,T,T);
117         printf("%d\n",-ans);
118     }
119 }
View Code

 

转载于:https://www.cnblogs.com/zhexipinnong/p/3353821.html


http://www.ppmy.cn/news/190331.html

相关文章

洛谷 P2715 约数和

给出a和b求a^b的约数和。 题目描述 输入输出格式 输入格式&#xff1a; 一行两个数a,b。 输出格式&#xff1a; 一个数表示结果对 9901 的模。 输入输出样例 输入样例#1&#xff1a; 2 3 输出样例#1&#xff1a; 15 说明 对于 30%的数据&#xff0c;a,b≤ 10 对于 100%的数据&a…

Dell p2415q DP 如何开启 60hz 模式, Macbook pro 2017

Dell p2415q DP 如何开启 60hz 模式, Macbook pro 2017 注意事项 背面的两个DP接口&#xff0c;一个是输入&#xff0c;一个是输出 靠近电源口的那个 DP 口是视频源输入口&#xff0c;远离电源口的那个是 DP 的输出口。 接输出口是没有效果的&#xff0c;那个口是用于连接多台…

Win10 电脑屏幕亮度随背景颜色变化而变化

Win10 电脑屏幕亮度随背景颜色变化而变化 我的电脑&#xff1a;DELL台式机XPS8700,显示器型号&#xff1a;P2715Q 问题描述&#xff1a; 电脑由WIN7系统升级为WIN10教育版后&#xff0c;查看图片如果图片是暗的&#xff0c;显示器就会慢慢变暗&#xff0c;关掉图片后显示器又…

【3000字帮你深度剖析数据在内存中的存储】

本节重点 -- 重中之重 数据类型详细介绍 整形在内存中的存储&#xff1a;原码、反码、补码 大小端字节序介绍及判断 浮点型在内存中的存储解析 准备好了&#xff0c;开始啰&#xff0c;在小小的花园里面......最近被这个歌曲洗脑&#xff0c;但是我们并不是要唱歌&#xff0c;而…

openresty离线rpm升级至openresty-1.19.9.1版本

注意&#xff1a;此方法步骤仅本人验证通过&#xff0c;要升级的话&#xff0c;需要做备份 1。系统版本是centos7(Linux version 3.10.0-693.el7.x86_64) 2。默认openresty版本是1.15.8.1 3。本次升级到openresty-1.19.9.1 目前系统是没有连接外网&#xff0c;只能进行rpm离…

哪款蓝牙耳机通话效果好?蓝牙耳机通话效果最好排名

现在的蓝牙耳机不仅仅是用来听音乐&#xff0c;还有需要接电话的的时候也可以用到&#xff0c;蓝牙耳机通话时不用手持手机并且没有线的牵绊&#xff0c;非常合适商务人士、旅游或者经常开车的人户&#xff0c;蓝牙耳机的款式和型号众多&#xff0c;哪款蓝牙耳机通话效果好呢&a…

蓝牙耳机什么牌子性价比高一些?综合性能强的蓝牙耳机推荐

近年来&#xff0c;智能手机更新迭代非常快&#xff0c;同时耳机更新迭代也是非常快&#xff0c;从之前的有线耳机到蓝牙耳机再到现在的真无线耳机&#xff0c;在一次一次的更新中&#xff0c;耳机从有线到无线&#xff0c;从透传到降噪。虽然升级到了真无线耳机&#xff0c;但…

无线蓝牙耳机什么牌子的好用?目前最好的无线蓝牙耳机

蓝牙耳机可以说是大家通用的产品了&#xff0c;毕竟在大家的日常生活中&#xff0c;都会用到它。不过不同的蓝牙耳机品牌产品之间的价格、配置、性能差异是非常明显的&#xff0c;有的小伙伴不懂蓝牙耳机&#xff0c;一不小心可能就会入坑&#xff0c;不过不要担心&#xff0c;…