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 = ...
随机推荐
- 我的docker 使用笔记
0 容器启动 docker run image_name(镜像名称) echo "hello word" 1 启动容器 退出后 重新进入 方法一 sudo docker exec ...
- android 50 进程优先级
程序在磁盘叫程序,程序加载到内存运行起来叫进程,优先级5个级别,内存不足的时候会杀掉低级别进程. Active Process:最上面用户可以操作的. Visible Process:可见进程,部分可 ...
- 亲测PHpnow 安装环境
出现问题1: "C:\Windows\system32\7z.exe"' 不是 或批处理文件. 找不到 C:\Windows\system32\7z.exe------------ ...
- FastDFS安装配置手册
文件服务器分布式系统安装手册 本文档详细的介绍了FastDFS的最小集群安装过程.集群环境如下: tracker:20.2.64.133 .用于调度工作,在访问上起负载均衡的作用. group1: s ...
- Android 使用Android Studio + Gradle 或 命令行 进行apk签名打包
官方文档:https://developer.Android.com/tools/publishing/app-signing.html 1. 默认为debug mode,使用的签名文件在: $HOM ...
- html input 文本框的一些操作(限制输入...)
1.取消按钮按下时的虚线框 在input里添加属性值 hideFocus 或者 HideFocus=true 2.只读文本框内容 在input里添加属性值 readonly 3.防止退后清空的TEXT ...
- TFS扩展开发中遇到的坑
本码农最近开发一个VS扩展,其中有些功能涉及到文件的签出.我们公司用的是TFS,遇到了一些奇特的现象,将解决过程记录如下. 一.明明在线的连接却Offline属性等于True public stati ...
- C# 多线程、结构体
struct IpAndPort { public string Ip; public int Port; } private void Form1_Load(object sender, Event ...
- 【POJ2886】【线段树】Who Gets the Most Candies?
Description N children are sitting in a circle to play a game. The children are numbered from 1 to N ...
- Vim简明教程【CoolShell】
vim的学习曲线相当的大(参看各种文本编辑器的学习曲线),所以,如果你一开始看到的是一大堆VIM的命令分类,你一定会对这个编辑器失去兴趣的.下面的文章翻译自<Learn Vim Progress ...