JZOJ 3447【NOIP2013模拟联考2】摘取作物
来源:互联网 发布:程序化交易策略源码 编辑:程序博客网 时间:2024/06/05 02:34
Description:
Feather的农场里有N*M块地,排列成N行,每行M块地。Feather在每块地里种植了不同的农作物。现在这些农作物都成熟了,可以摘取下来出售了。其中第i行第j列的地里的农作物的价值为W[i,j]。
JackRabbit是Feather的好友,平时经常为Feather的农作物除草除虫。为了答谢JackRabbit,Feather决定把一部分农作物送给JackRabbit。JackRabbit很高兴,恨不得一下子把农场里的农作物摘空。
为了防止JackRabbit把农作物摘空,Feather提出了两个条件:
1.每行最多选取两块地;
2.每列最多选取两块地。
这下子把JackRabbit难住了。如何在满足这两个条件的前提下,使得摘取的农作物的价值之和最大呢?
Input:
第一行是两个整数N和M(3≤N≤30,3≤M≤30)。
以下N行每行M个整数,表示每块地的农作物的价值W[i,j](0≤W[i,j]≤10000)。
Output:
输出一个数,表示在满足条件的前提下摘取的农作物的价值之和的最大值。
Sample Input:
3 3
1 5 3
4 7 5
0 4 1
Sample Output:
21
【样例说明】
第一行选5和3,第二行选4和5,第三行选0和4,总和为21,是满足条件的最佳选取方案。
Data Constraint
40% n,m<=10
100% n,m<=30
题目大意:
给一个n*m的矩阵,每一行、每一列只能选两个数,求选出的数的和最大是多少。
题解:
当时我正在做其它题,前面的ifleaking转过来说:“不会网络流,随便来一题都不会”。
我一看,这不是费用流吗?于是开森地打了个最大费用最大流,WA50。
这个方法:
x坐标做一群点,源点到它们连流量为2,费用为0的弧.
y坐标做一群点,它们到汇点连流量为2费用为0的弧。
x到y连流量为1,费用为对应的作物值。
哦。原来是可行流啊。
zkw费用流怎么改可行流啊?上zkw博客,什么鬼,看不懂。
某LL说用SPFA就好了,于是看了一波题解,虽然不会证,好像挺有道理。
SPFA详见这里
但zkw怎么改啊?啊?啊?
某Wyt说,你建一些两排两列空点不就好了吗?
哇,肿么就辣么机智呢?
Code:
#include<cstdio>#include<cstring>#define fo(i, x, y) for(int i = x; i <= y; i ++)#define min(a, b) ((a) < (b) ? (a) : (b))using namespace std;const int INF = 1 << 30, M = 10000;int n, m, a[35][35];int final[80], tot = 1;struct node { int to, next, r, w;}e[5000];int S, T, bz[80], dis[80];int ans1, ans2;void link(int x, int y, int r, int w) { e[++ tot].next = final[x], e[tot].to = y, e[tot].r = r, e[tot].w = w, final[x] = tot; e[++ tot].next = final[y], e[tot].to = x, e[tot].r = 0, e[tot].w = -w, final[y] = tot;}void Init() { scanf("%d %d", &n, &m); fo(i, 1, n) fo(j, 1, m) scanf("%d", &a[i][j]); n += 2; m += 2; fo(i, 1, n) fo(j, 1, m) link(i, j + n, 1, M - a[i][j]); S = n + m + 1, T = S + 1; fo(i, 1, n) link(S, i, 2, 0); fo(i, 1, m) link(i + n, T, 2, 0); link(T, S, INF, -INF);}int aug(int x, int flow) { if(x == T) { ans1 += flow; ans2 += dis[S] * flow; return flow; } bz[x] = 1; int use = 0; for(int i = final[x]; i; i = e[i].next) if(!bz[e[i].to] && e[i].r && dis[x] == dis[e[i].to] + e[i].w) { int tmp = aug(e[i].to, min(flow - use, e[i].r)); e[i].r -= tmp; e[i ^ 1].r += tmp; use += tmp; if(use == flow) return use; } return use;}bool change() { int minh = INF; fo(i, 1, T) if(bz[i]) for(int k = final[i]; k; k = e[k].next) if(e[k].r && !bz[e[k].to]) minh = min(minh, dis[e[k].to] + e[k].w - dis[i]); if(minh == INF) return 0; fo(i, 1, T) if(bz[i]) dis[i] += minh; return 1;}int main() { freopen("pick.in", "r", stdin); freopen("pick.out", "w", stdout); Init(); do do memset(bz, 0, sizeof(bz)); while(aug(S, INF)); while(change()); printf("%d", ans1 * M - ans2);}
- JZOJ 3447【NOIP2013模拟联考2】摘取作物
- 【NOIP2013模拟联考2】摘取作物(pick)
- JZOJ 3498【NOIP2013模拟联考14】图形变换
- jzoj. 3450. 【NOIP2013模拟联考3】山峰(summits)
- JZOJ 3468. 【NOIP2013模拟联考7】OSU!(osu)
- [jzoj]3479. 【NOIP2013模拟联考9】工作安排(work)
- 【JZOJ 3492】【NOIP2013模拟联考12】数数(count)
- 摘取作物
- 摘取作物
- [jzoj]3499. 【NOIP2013模拟联考15】人类基因组(genes) (单调队列、前缀和、线段树解一题)
- [jzoj]3498. 【NOIP2013模拟联考14】图形变换(transform) (计算几何+矩阵乘法)
- jzoj 3467. 【NOIP2013模拟联考7】最长上升子序列(lis) dfs+lis+手工栈
- [jzoj]3468. 【NOIP2013模拟联考7】OSU!(osu) (期望DP)
- [jzoj]3472. 【NOIP2013模拟联考8】匹配(match)(AC自动机+DP)
- [jzoj]3486. 【NOIP2013模拟联考10】道路改建(rebuild)(缩环+Tarjan+拓扑+bitset记录状态)
- [jzoj]3480. 【NOIP2013模拟联考9】阿Q的停车场(park)(线段树+堆)
- 【NOIP2013模拟联考13】线段
- 【NOIP2013模拟联考7】数列
- CaysnPrinter
- java影院票务管理系统项目开发计划
- 一个网站 Code/Android/
- 深度学习训练模型调参策略
- 柯洁大战 AlphaGo 三盘皆输
- JZOJ 3447【NOIP2013模拟联考2】摘取作物
- Tensorflow计算、数据和运行模型
- Codevs1213 解的个数
- matlab:绘制三维曲线
- Spring学习笔记之缓存数据
- Linux搭建DOS编程环境
- 两个数之和C语言实现
- Wampserver一直是橙色的
- 文章标题