POJ 3422 矩阵取数 最小费用流拆点+负边
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 9153 | Accepted: 3696 |
Description
On an N × N chessboard with a non-negative number in each grid, Kaka starts his matrix travels with SUM = 0. For each travel, Kaka moves one rook from the left-upper grid to the right-bottom one, taking care that the rook moves only to the right or down. Kaka adds the number to SUM in each grid the rook visited, and replaces it with zero. It is not difficult to know the maximum SUM Kaka can obtain for his first travel. Now Kaka is wondering what is the maximum SUM he can obtain after his Kth travel. Note the SUM is accumulative during the K travels.
Input
The first line contains two integers N and K (1 ≤ N ≤ 50, 0 ≤ K ≤ 10) described above. The following N lines represents the matrix. You can assume the numbers in the matrix are no more than 1000.
Output
The maximum SUM Kaka can obtain after his Kth travel.
Sample Input
3 2
1 2 3
0 2 1
1 4 2
Sample Output
Source
- 有个方阵,每个格子里都有一个非负数,从左上角走到右下角,每次走一步,只能往右或往下走,经过的数字拿走
- 每次都找可以拿到数字和最大的路径走,走k次,求最大和
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <algorithm>
#include <set>
using namespace std;
#define MM(a,b) memset(a,b,sizeof(a))
typedef long long ll;
typedef unsigned long long ULL;
const int mod = 1000000007;
const double eps = 1e-10;
const int inf = 0x3f3f3f3f;
const int big=50000;
int max(int a,int b) {return a>b?a:b;};
int min(int a,int b) {return a<b?a:b;};
const int N = 70;
const int M=10000+100;
struct edge{
int to,cap,cost,rev;
}; vector<edge> G[5005];
int mp[55][55], dist[5005],inq[5005],prev[5005],prel[5005];
struct Point{
int x,y;
}; int n,k,m,x,y,c,cnth,cntm; void add_edge(int u,int v,int cap,int cost)
{
G[u].push_back(edge{v,cap,cost,G[v].size()});
G[v].push_back(edge{u,0,-cost,G[u].size()-1});
} int mincost(int s,int t,int f)
{
int ans=0;
while(f>0)
{
memset(dist,inf,sizeof(dist));
memset(inq,0,sizeof(inq));
dist[s]=0;
queue<int> q;
q.push(s);
inq[s]=1;
MM(prev,-1);
while(!q.empty())
{
int u=q.front();
q.pop();inq[u]=0;
for(int j=0;j<G[u].size();j++)
{
edge &e=G[u][j];
if(e.cap>0&&dist[e.to]>dist[u]+e.cost)
{
dist[e.to]=dist[u]+e.cost;
prev[e.to]=u;
prel[e.to]=j;
if(!inq[e.to])
{
q.push(e.to);
inq[e.to]=1;
}
}
}
}
for(int i=t;i>s;)
{
int f=prev[i];
if(f==-1) return -1;
int j=prel[i];
G[f][j].cap-=1;
G[i][G[f][j].rev].cap+=1;
ans+=G[f][j].cost;
i=prev[i];
}
f-=1;
}
return ans;
} int in(int i,int j)
{
return (i-1)*2*n+j;
} int out(int i,int j)
{
return (i-1)*2*n+n+j;
} void build(int k)
{
add_edge(0,1,k,0); for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
add_edge(in(i,j),out(i,j),1,-mp[i][j]);
add_edge(in(i,j),out(i,j),k-1,0);
} for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
if(i!=n)
add_edge(out(i,j),in(i+1,j),k,0);
if(j!=n)
add_edge(out(i,j),in(i,j+1),k,0);
} add_edge(out(n,n),out(n,n)+1,k,0);
} int main()
{
while(~scanf("%d %d",&n,&k))
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%d",&mp[i][j]);
build(k);
printf("%d\n",-mincost(0,out(n,n)+1,k));
}
return 0;
}分析:1.建图时一个节点拆成两个,并且中间连接两条边,一条是费用该点的价值取反,另一条是为了保证这个节点能经过多次
2因为是最小费用流,所以需要将费用取反,跑完最小费用流后再取反就好
POJ 3422 矩阵取数 最小费用流拆点+负边的更多相关文章
- 51Nod 1084 矩阵取数问题 V2 —— 最小费用最大流 or 多线程DP
题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1084 1084 矩阵取数问题 V2 基准时间限制:2 秒 空 ...
- NOIP2007 矩阵取数游戏
题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2. ...
- NOIP2007矩阵取数[DP|高精度]
题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2. ...
- TYVJ 矩阵取数 Label:高精度+dp
题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2. ...
- 【NOIP2007】矩阵取数
因为傻逼写错高精度搞了一下午浪费好多时间,好想哭qaq 原题: 帅帅经常更同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij据为非负整数.游戏规则如下: 1. 每次取数时须从每 ...
- 51nod1084 矩阵取数问题 V2
O(n4)->O(n3)妈呀为什么跑这么慢woc #include<cstdio> #include<cstring> #include<cctype> #i ...
- 1166 矩阵取数游戏[区间dp+高精度]
1166 矩阵取数游戏 2007年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description [ ...
- 矩阵取数游戏 NOIP 2007
2016-05-31 17:26:45 题目链接: NOIP 2007 矩阵取数游戏(Codevs) 题目大意: 给定一个矩阵,每次在每一行的行首或者行尾取一个数乘上2^次数,求取完最多获得的分数 解 ...
- 洛谷 P1005 矩阵取数游戏
题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2. ...
随机推荐
- Linux下面查看网卡的信息
查看linux下面网卡的速度信息 Study From 百度知道 (懒得翻墙) 1. centos机器 安装的比较全(个人比较懒 没有使用core最小化安装, 避免出问题麻烦 公司网络太垃圾) 使用 ...
- [转帖]天津飞腾回应处理器造假 没有采用ARM的内核,内核自主设计
天津飞腾回应处理器造假没有采用ARM的内核,内核自主设计 ... https://www.expreview.com/63233.html 看了下 同意孟宪瑞老师的关系 飞腾 的确改动了 ARM的架构 ...
- 最大两队竞争值(暴力dfs)--牛客多校第二场
题意: 给你2n个人,两两有对立竞争值,问你分成两队最大的竞争值是多少. 思路: 直接暴力dfs,稍微有点卡,3800ms. #include<iostream> #include< ...
- js跳转页面的方法
js跳转页面的几种方法 第一种:(跳转到b.html) <script language="javascript" type="text/javascript&qu ...
- sql server case when
case具有两种格式:简单Case函数和Case搜索函数 简单case函数 实例:CASE sex when '1' then '男' when '2' then'女' els ...
- sql--ALTER
ALTER TABLE 语句 ALTER TABLE 语句用于在已有的表中添加.修改或删除列. SQL ALTER TABLE 语法 如需在表中添加列,请使用下列语法: ALTER TABLE tab ...
- python 一键登录微信分析好友性别 地址 生成结果
# -*- coding:utf- -*- """ author:Mr Yang data:// """ import itchat imp ...
- linux复习6
ubuntu------------- apt //advanced package tool,高级包工具. apt-get install centos------------- yum //yel ...
- 11 Python之初识函数
---恢复内容开始--- 1. 什么是函数? f(x) = x + 1 y = x + 1 函数是对功能或者动作的封装 2. 函数的语法和定义 def 函数名(): 函数体 调用: 函数名() 3. ...
- ES6入门之Proxy
1. 概述 Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种『元编程』即对编程语言进行编程. 1.1 理解 Proxy 是在目标对象之前架设一层『拦截』,外部对对象的访问 ...