Jump
hdu4862:http://acm.hdu.edu.cn/showproblem.php?pid=4862
题意:给你n*m的方格,每个方格中有一个数(0---9),然后你每次可以选择一个点开始,这个点是之前没有访问过的,然后你可以向右边的的方格跳,也可以向下面的方格跳。跳的过程中,你会丢失(x2-x1)+(y2-y1)-1一些能量。如果下一个方格和现在的方格的数字相同,那么你可以得到一些能量。每次一开始,你就可以随便跳。但是你最多只能选择k次开始。为你得到的最多能量,并且每个格子只访问一次。
题解:剖析一下,就知道,这一题是求最小k条路径覆盖(如果把边权取负的话)。接下是如果求解这个模型。建图方式如下。

把原图中点分成两部分X(n*m个),Y(n*m个),原图中的边(u,v,w),改成(u,v+n*m,-w);然后源点与X部分的每一点建一条边(st,x,0),然后st与p之间建一条边(st,p,0),容量为k,然后p与Y的每一点建一条边,然后Y与汇点建立一条边,这些变的容量都是1,费用都是0.然后跑最小费用最大流,如果满流则能跑完每个格子一次。否则不能。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define inf 100000000
using namespace std;
const int E=;
const int N=;
struct{
int v, cap, cost, next; // re记录逆边的下标。
}edge[E];
int n, m, ans,flow;
int k, cnt,head[N];
int que[N], pre[N], dis[N];
bool vis[N];
char mp[][];
void init(){//初始化
cnt=ans=,flow=;
memset(head,-,sizeof(head));
}
void addEdge(int u, int v, int ca, int co){
edge[cnt].v = v;
edge[cnt].cap = ca;
edge[cnt].cost = co;
edge[cnt].next = head[u];
head[u] = cnt ++;
edge[cnt].v = u;
edge[cnt].cap = ;
edge[cnt].cost = -co;
edge[cnt].next = head[v];
head[v] = cnt++;
}
bool spfa(){ // 源点为0,汇点为n。
int i;
for(i = ; i <= *m*n+; i ++){
dis[i] = inf;
vis[i] = false;
}
queue<int>Q;
Q.push(*n*m+);
dis[*n*m+]=;
vis[*n*m+] = true;
while(!Q.empty()){ // 这里最好用队列,有广搜的意思,堆栈像深搜。
int u = Q.front();
Q.pop();
for(i = head[u]; i != -; i = edge[i].next){
int v = edge[i].v;
if(edge[i].cap && 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);
}
}
}
vis[u] = false;
}
if(dis[*n*m+] == inf) return false;
return true;
}
void end(){
int u, p, sum = inf;
for(u = *n*m+; u !=*n*m+; u = edge[p^].v){//0是超级源点
p = pre[u];
sum = min(sum, edge[p].cap);
}
for(u = *n*m+; u != *n*m+; u = edge[p^].v){
p = pre[u];
edge[p].cap -= sum;
edge[p^].cap += sum;
ans += sum * edge[p].cost; // cost记录的为单位流量费用,必须得乘以流量。
}
flow+=sum;
} void input(){
memset(mp,,sizeof(mp));
for(int i=;i<=n;i++){
for(int j=;j<=m;j++)
cin>>mp[i][j];
}
}
void build(){
for(int i=;i<=n;i++)
for(int j=;j<=m;j++){
for(int k=j+;k<=m;k++){
if(mp[i][j]==mp[i][k])
addEdge((i-)*m+j,(i-)*m+k+n*m,,k-j--(mp[i][j]-''));
else
addEdge((i-)*m+j,(i-)*m+k+n*m,,k-j-); }
for(int k=i+;k<=n;k++){
if(mp[i][j]==mp[k][j])
addEdge((i-)*m+j,(k-)*m+j+n*m,,k-i--(mp[i][j]-''));
else
addEdge((i-)*m+j,(k-)*m+j+n*m,,k-i-);
} }
for(int i=;i<=n*m;i++){
addEdge(*m*n+,i,,);
addEdge(,i+n*m,,);
addEdge(i+n*m,*n*m+,,);
}
addEdge(*n*m+,,k,);
}
int cas;
int main(){
int tt=;
scanf("%d",&cas);
while(cas--){
scanf("%d%d%d",&n,&m,&k);
input();
init();
build();
while(spfa())end();
if(flow==n*m){
printf("Case %d : %d\n",tt++,-ans);
}
else{
printf("Case %d : -1\n",tt++);
}
}
}
Jump的更多相关文章
- [LeetCode] Frog Jump 青蛙过河
A frog is crossing a river. The river is divided into x units and at each unit there may or may not ...
- [LeetCode] Jump Game 跳跃游戏
Given an array of non-negative integers, you are initially positioned at the first index of the arra ...
- [LeetCode] Jump Game II 跳跃游戏之二
Given an array of non-negative integers, you are initially positioned at the first index of the arra ...
- Leetcode 45. Jump Game II
Given an array of non-negative integers, you are initially positioned at the first index of the arra ...
- Leetcode 55. Jump Game
我一开始认为这是一道DP的题目.其实,可以维护一个maxReach,并对每个元素更新这个maxReach = max(maxReach, i + nums[i]).注意如果 i>maxReach ...
- LeetCode 笔记系列13 Jump Game II [去掉不必要的计算]
题目: Given an array of non-negative integers, you are initially positioned at the first index of the ...
- Leetcode jump Game II
Given an array of non-negative integers, you are initially positioned at the first index of the arra ...
- Leetcode jump Game
Given an array of non-negative integers, you are initially positioned at the first index of the arra ...
- bug report: Jump to the invalid address stated on the next line at 0x0: ???
gdb或者vlagrind报告: ==14569== Jump to the invalid address stated on the next line ==14569== at 0x0: ??? ...
- Jump Game 的三种思路 - leetcode 55. Jump Game
Jump Game 是一道有意思的题目.题意很简单,给你一个数组,数组的每个元素表示你能前进的最大步数,最开始时你在第一个元素所在的位置,之后你可以前进,问能不能到达最后一个元素位置. 比如: A = ...
随机推荐
- TColorPickerButton组件
http://files.cnblogs.com/xe2011/VCL_TColorPB12.rar 在DELPHI7中可以正常使用 在DELPHI XE5中 下面会有些问题 安装方法 打开 DELP ...
- Struts 有哪些经常使用标签库
Struts 有哪些经常使用标签库 1.html标签库 2.bean标签库 3.logic标签库
- Bit data type
mysql> create table t(a bit()); Query OK, rows affected (0.04 sec) mysql> insert into t '; Que ...
- MapReduce输出格式
针对前面介绍的输入格式,MapReduce也有相应的输出格式.默认情况下只有一个 Reduce,输出只有一个文件,默认文件名为 part-r-00000,输出文件的个数与 Reduce 的个数一致. ...
- [转] How to dispatch a Redux action with a timeout?
How to dispatch a Redux action with a timeout? Q I have an action that updates notification state of ...
- Java基础知识强化之集合框架笔记38:Set集合之Set集合概述和特点
1. Set集合概述和特点 Collection |--List 有序(存储顺序和取出顺序一致),可重复 |--Se ...
- css 权威指南笔记( 五)结构和层叠之三种样式来源
CSS中的样式一共有三种来源:创作人员.读者和用户代理,来源的不同会影响到样式的层叠方式 首先,创作人员(author's+style)样式应该是我们最熟悉的,如果你是一个前端开发者,那么你写的那些样 ...
- js数组操作的常用方法
数组:arr=[1,2,3,4,5]; 1.数组转换成字符串,不会修改原数组内容: arr.join(); // "1,2,3,4,5" arr.join("" ...
- ^(bitwise exclusive Or).
一个数,进行异或同一个数两次,将得到原来的数,例如: 6 ^ 4 ^ 4 = 6; 0000-0000-0000-0110 ^ 0000-0000-0000-0100 ---------------- ...
- 在oracle中怎么把一张表的数据插入到另一张表中
把table2表的数据插入到table1中 insert into table1 select * from table2