洛谷 - P2045 - 方格取数加强版 - 费用流
原来这种题的解法是费用流。
从一个方格的左上走到右下,最多走k次,每个数最多拿走一次。
每次走动的流量设为1,起始点拆点成限制流量k。
每个点拆成两条路,一条路限制流量1,费用为价值相反数。另一条路无限流量。
跑一遍费用流。
#include<bits/stdc++.h>
using namespace std; const int MAXN=+;
const int MAXM=;
const int INF=0x3f3f3f3f;
struct Edge{
int to,next,cap,flow,cost;
}edge[MAXM];
int head[MAXN],tol;
int pre[MAXN],dis[MAXN];
bool vis[MAXN]; int n;
void init(){
tol=;
memset(head,-,sizeof(head));
} void addedge(int u,int v,int cap,int cost){
edge[tol].to=v;
edge[tol].cap=cap;
edge[tol].cost=cost;
edge[tol].flow=;
edge[tol].next=head[u];
head[u]=tol++; edge[tol].to=u;
edge[tol].cap=;
edge[tol].cost=-cost;
edge[tol].flow=;
edge[tol].next=head[v];
head[v]=tol++;
} bool spfa(int s,int t){
queue<int> q;
memset(dis,INF,sizeof(dis));
memset(vis,false,sizeof(vis));
memset(pre,-,sizeof(pre)); dis[s]=;
vis[s]=true;
q.push(s);
while(!q.empty()){
int u=q.front();
q.pop();
vis[u]=false;
for(int i=head[u];i!=-;i=edge[i].next){
int v=edge[i].to;
if(edge[i].cap>edge[i].flow&&dis[v]>dis[u]+edge[i].cost){
dis[v]=dis[u]+edge[i].cost;
pre[v]=i;
if(!vis[v]){
vis[v]=true;
q.push(v);
}
}
}
}
if(pre[t]==-)
return false;
else
return true;
} int minCostMaxFlow(int s,int t,int &cost){
int flow=;
cost=;
while(spfa(s,t)){
int Min=INF;
for(int i=pre[t];i!=-;i=pre[edge[i^].to]){
if(Min>edge[i].cap-edge[i].flow)
Min=edge[i].cap-edge[i].flow;
}
for(int i=pre[t];i!=-;i=pre[edge[i^].to]){
edge[i].flow+=Min;
edge[i^].flow-=Min;
cost+=edge[i].cost*Min;
}
flow+=Min;
}
return flow;
} void show(int s){
bool vis[];
queue<int> q;
vis[s]=;
q.push(s);
while(!q.empty()){
int u=q.front();
q.pop();
cout<<"u="<<u<<endl;
for(int i=head[u];i!=-;i=edge[i].next){
int v=edge[i].to;
if(vis[v]==){
vis[v]=;
q.push(v);
}
}
}
cout<<endl;
} /* EK end */ int a[][]; int k; inline int getid(int i,int j,int isout){
return (i-)*n+j+isout*(n*n);
} int main(){
init();
scanf("%d%d",&n,&k); int si=*n*n+,so=*n*n+;
addedge(si,so,k,);//最多走k次
int t=*n*n+; for(int i=;i<=n;i++){
for(int j=;j<=n;j++){
int c;
scanf("%d",&c);
addedge(getid(i,j,),getid(i,j,),,-c);
//拿走它,获得价值,费用是相反数
addedge(getid(i,j,),getid(i,j,),INF,);
//不拿就不拿呗
}
} for(int i=;i<=n;i++){
for(int j=;j<=n;j++){
if(i+<=n)
addedge(getid(i,j,),getid(i+,j,),INF,);
if(j+<=n)
addedge(getid(i,j,),getid(i,j+,),INF,);
}
} addedge(so,getid(,,),INF,);
addedge(getid(n,n,),t,INF,); //show(si); int cost=;
int flow=minCostMaxFlow(si,t,cost);
printf("%d\n",-cost); }
洛谷 - P2045 - 方格取数加强版 - 费用流的更多相关文章
- 洛谷P2045 方格取数加强版(费用流)
题意 题目链接 Sol 这题能想到费用流就不难做了 从S向(1, 1)连费用为0,流量为K的边 从(n, n)向T连费用为0,流量为K的边 对于每个点我们可以拆点限流,同时为了保证每个点只被经过一次, ...
- 洛谷 P2045 方格取数加强版【费用流】
题目链接:https://www.luogu.org/problemnew/show/P2045 题目描述 给出一个n*n的矩阵,每一格有一个非负整数Aij,(Aij <= 1000)现 ...
- 洛谷P2045 方格取数加强版 最小费用流
Code: #include<cstdio> #include<cstring> #include<algorithm> #include<queue> ...
- [洛谷P2045]方格取数加强版
题目大意:有一个n*n的矩阵,每个格子有一个非负整数,规定一个人从(1,1)开始,只能往右或下走,走到(n,n)为止,并把沿途的数取走,取走后数变为0.这个人共取n次,求取得的数的最大总和. 解题思路 ...
- LG2045 方格取数加强版 费用流
问题描述 LG2045 题解 费用流. 套路拆点,把\((i,j)\)拆为两个点,在这两个点之间连边:一条边流量为\(1\),费用为\(a_{i,j}\),另一条边为流量为\(INF\),费用为\(0 ...
- P2045 方格取数加强版
P2045 方格取数加强版 题目描述 给出一个n*n的矩阵,每一格有一个非负整数Aij,(Aij <= 1000)现在从(1,1)出发,可以往右或者往下走,最后到达(n,n),每达到一格,把该格 ...
- 棋盘DP三连——洛谷 P1004 方格取数 &&洛谷 P1006 传纸条 &&Codevs 2853 方格游戏
P1004 方格取数 题目描述 设有N $\times N$N×N的方格图(N $\le 9$)(N≤9),我们将其中的某些方格中填入正整数,而其他的方格中则放入数字00.如下图所示(见样例): A ...
- 洛谷 P2774 方格取数问题 解题报告
P2774 方格取数问题 题目背景 none! 题目描述 在一个有 \(m*n\) 个方格的棋盘中,每个方格中有一个正整数.现要从方格中取数,使任意 2 个数所在方格没有公共边,且取出的数的总和最大. ...
- 洛谷 P1004 方格取数 题解
P1004 方格取数 题目描述 设有 \(N \times N\) 的方格图 \((N \le 9)\),我们将其中的某些方格中填入正整数,而其他的方格中则放入数字\(0\).如下图所示(见样例): ...
随机推荐
- [原创]安装Ubuntu Server 14.04后
安装后许多软件都没有,需要进行安装. 官方指南:https://help.ubuntu.com/lts/serverguide/index.html 1.修改网络配置文件 用ifconfig查看本地网 ...
- 最近遇到的C++数字和字符串的转换问题
1. 用itoa 和atoi 在头文件#include<cstidlib> itoa用法: char * itoa ( int value, char * str, int base ) ...
- java开始到熟悉61
本此主题:多维数组----矩阵运算 矩阵的运算规则是将对应位置的值进行运算,如上图所示. package array; public class Matrix { /** * 打印矩阵 * @para ...
- (转)gcc学习笔记
1.gcc -Wall hello.c -o hello //编译源文件,显示警告信息 2../a.out //运行程序 3.gcc -Wall calc.c /usr/lib/libm.a -o ...
- Redis 脚本及其应用
参考:http://www.runoob.com/redis/redis-scripting.html Redis 脚本使用 Lua 解释器来执行脚本. Reids 2.6 版本通过内嵌支持 Lua ...
- glib的安装(2)
一: glib库的路径: http://ftp.acc.umu.se/pub/GNOME/sources/glib/2.20/ 二: 下载glib库: wget http://ftp.acc. ...
- homebrew -v 或homebrew -doctor报错请检查 .bash_profile是否有误
homebrew -doctor报错: /usr/local/Library/Homebrew/global.rb:109:in `split': invalid byte sequence in U ...
- NCR Teradata银行业数据仓库解决方案
NCR Teradata银行业数据仓库解决方案 ---------------------------------------------------------------------------- ...
- 关闭SVN服务
关闭TSVNCache.exe进程 在Windows下使用SVN,通常都会安装TortoiseSVN,安装后会有一个TSVNCache.exe的进程驻留内存,这个进程会定时地去扫描Subversion ...
- IOS中UIAlertView(警告框)常用方法总结
一.初始化方法 - (instancetype)initWithTitle:(NSString *)title message:(NSString*)message delegate:(id /*&l ...