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 = ...
随机推荐
- 银行B2C直连
银行B2C直连: 1. 银联B2C直连流程: 注: 所有银行B2C接入方式均为此流程. 不同银行只是签名及验签方式不一致,请求及返回参数不一样,其他的一致. 2. 银行B2C支付请求: 交易流程: ( ...
- TOJ 2732存钱计划(三)(单源最短路)
存钱计划(三) 时间限制(普通/Java):1000MS/30000MS 运行内存限制:65536KByte 总提交: 18 测试通过: 16 描述 TZC的店铺比较 ...
- iOS-UITableCell详情
iOS-UITableCell详情 表示UITableViewCell风格的常量有: UITableViewCellStyleDefault UITableViewCellStyleSubtitle ...
- xslt语法之---运算符号
<xsl:param name="count">12</xsl:param > <xsl:template match="/" ...
- c++矩阵运算
优化了一些算法 #pragma once #include <iostream> #include <iomanip> #include <string> #def ...
- SQL Server中的死锁
简介 死锁的本质是一种僵持状态,是多个主体对于资源的争用而导致的.理解死锁首先需要对死锁所涉及的相关观念有一个理解. 一些基础知识 要理解SQL Server中的死锁,更好的方式是通过类比从更大的面理 ...
- IOC之Unity
项目最近用到,查找到比较好的资料,记录哈: Unity 3(一):简介与示例: Unity 3(二):Unity在AOP方面的应用
- X3850 Linux 下DSA日志收集办法
收集工具下载 RHEL 6: 32bit-- [IBM 下载]http://delivery04.dhe.ibm.com/sar/CMA/XSA/03tza/1/ibm_utl_dsa_dsytb7x ...
- Cocos2dx开发(3)——Cocos2dx打包成APK,ANT环境搭建
前面cocos2dx的运行环境(Android SDK,JDK,),最后Cocos2dx的APK的打包环境,最运行环境上再加ANT环境就好了 1.ANT下载配置 官网下载:http://ant.apa ...
- C++最后课程项目总结
第一次独立完成的C++小项目,40小时 + 5小时Update + 8小时Linux移植. 过程: 过程非常认真,一个星期主要就是忙这个,为了完成某个部分,有时饭都推迟吃,连续对着电脑10几个小时很累 ...