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 = ...
随机推荐
- 【网络通信】服务器端Socket监听80端口,建立连接传输数据时也是使用的80端口么?
1. 服务器端Socket监听80端口,建立连接传输数据时也是使用的80端口么? 答:对.建立连接时服务器会分配一个新的Socket,但是用的源端口号还是80端口.套接字是由协议类型.源IP.目的IP ...
- Entity Framework CodeFirst------使用CodeFirst方式建立数据库连接(一)
本文分步演练介绍通过 Code First 开发建立新数据库.这个方案包括建立不存在的数据库(Code First 创建)或者空数据库(Code First 向它添加新表).借助 Code First ...
- MySQL(10):实体、实体表和外键(foreign key)
1.实体 数据库管理系统中的各种用于数据管理方便而设定的各种数据管理对象,如:数据库表.视图.存储过程等都是数据库实体.广义上讲,这些对象中所存储的数据也是数据库实体.因为它们也是确切存 ...
- 第五篇:python高级之面向对象高级
python高级之面向对象高级 python高级之面向对象高级 本节内容 成员修饰符 特殊成员 类与对象 异常处理 反射/自省 单例模式 1.成员修饰符 python的类中只有私有成员和公有成员两 ...
- codevs 1817 灾后重建
/* 暴力暴力 离线每次添边 堆优化dij 70 SPFA 80..... */ #include<iostream> #include<cstdio> #include< ...
- Axiom3D学习日记 4.地形,天空,雾
首先需要引用Axiom.SceneManagers.Octree.dll. 地形: 载入地形配置,从一个文件中. scene.LoadWorldGeometry( "Terrain.xml& ...
- 【转】无废话WCF系列教程
转自:http://www.cnblogs.com/iamlilinfeng/category/415833.html 看后感:这系列的作者李林峰写得真的不错,通过它的例子,让我对WCF有了一 ...
- java获取数据库数据表的元数据
Connction conn; DatabaseMetaData dmd=conn.getMetaData();//获取数据库元数据 PreparedStatment ps; ps.getParame ...
- PHP框架_ThinkPHP基础
目录 1.ThinkPHP项目结构 2.ThinkPHP运行流程 3.ThinkPHP配置文件 4.ThinkPHP四种URL模式 5.ThinkPHP用户自定义函数 6.ThinkPHP模板展示及变 ...
- HTML5-黑客帝国2D
<!DOCTYPE html><html> <head> <meta charset="utf-8"> <title>& ...