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的更多相关文章

  1. [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 ...

  2. [LeetCode] Jump Game 跳跃游戏

    Given an array of non-negative integers, you are initially positioned at the first index of the arra ...

  3. [LeetCode] Jump Game II 跳跃游戏之二

    Given an array of non-negative integers, you are initially positioned at the first index of the arra ...

  4. Leetcode 45. Jump Game II

    Given an array of non-negative integers, you are initially positioned at the first index of the arra ...

  5. Leetcode 55. Jump Game

    我一开始认为这是一道DP的题目.其实,可以维护一个maxReach,并对每个元素更新这个maxReach = max(maxReach, i + nums[i]).注意如果 i>maxReach ...

  6. LeetCode 笔记系列13 Jump Game II [去掉不必要的计算]

    题目: Given an array of non-negative integers, you are initially positioned at the first index of the ...

  7. Leetcode jump Game II

    Given an array of non-negative integers, you are initially positioned at the first index of the arra ...

  8. Leetcode jump Game

    Given an array of non-negative integers, you are initially positioned at the first index of the arra ...

  9. 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: ??? ...

  10. Jump Game 的三种思路 - leetcode 55. Jump Game

    Jump Game 是一道有意思的题目.题意很简单,给你一个数组,数组的每个元素表示你能前进的最大步数,最开始时你在第一个元素所在的位置,之后你可以前进,问能不能到达最后一个元素位置. 比如: A = ...

随机推荐

  1. 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(45)-工作流设计-设计步骤

    原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(45)-工作流设计-设计步骤 系列目录 步骤设计很重要,特别是规则的选择. 我这里分为几个规则 1.按自行 ...

  2. Present ViewController Modally

    一.主要用途 弹出模态ViewController是IOS变成中很有用的一个技术,UIKit提供的一些专门用于模态显示的ViewController,如UIImagePickerController等 ...

  3. calltree查看工程代码中的函数调用关系

    http://blog.csdn.net/elitemouse/article/details/41680113 http://www.tinylab.org/callgraph-draw-the-c ...

  4. iOS--NSAttributedString使用介绍

    iOS–NSAttributedString使用介绍 原文见: http://www.itnose.net/detail/6177538.html http://***/html/topnews201 ...

  5. 【Android】广播BrocastReceiver

    1.Android中广播主要分为两种:标准广播和有序广播. 标准广播:完全异步执行.广播发出后,所有的广播接收器几乎在同一刻收到广播事件,没有先后顺序之分. 优点:效率高 缺点:不能被截断 有序广播: ...

  6. MySQL日志概述

    为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处.LaplaceDemon/SJQ. http://www.cnblogs.com/shijiaqi1066/p/3859866.html ...

  7. 关于mvc 分页的 这两个结合着用

    http://www.cnblogs.com/JackFeng/archive/2010/01/25/JackFeng.html http://www.webdiyer.com/mvcpager/de ...

  8. HTML5-36d嗨起^_^

    如果一个前端不会写css那必然会被贻笑大方,利用html5新增的一些c3属性可以做许许多多炫酷的效果. 大家先看我写的一个小demo: http://zpf92.github.io/build/ 这个 ...

  9. Android开发手记(32) 使用摄像头拍照

    在Android中,使用摄像头拍照一般有两种方法, 一种是调用系统自带的Camera,另一种是自己写一个摄像的界面. 我们要添加如下权限: <uses-permission android:na ...

  10. 收集 数据库的awr数据,生成报告

    该脚本只是把awr报告的内容,原封不动的 展现出来,做记录 awrreport.sql  脚本内容如下: *********************************************** ...