多校联赛第一场(hdu4862)

Jump

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 644    Accepted Submission(s): 275

Problem Description
There are n*m grids, each grid contains a number, ranging from 0-9. Your initial energy is zero. You can play up to K times the game, every time you can choose any one of the grid as a starting point (but not traveled before) then
you can choose a grid on the right or below the current grid to jump, but it has not traveled before. Every time you can jump as many times as you want, as long as you do not violate rules. If you are from (x1, y1) to (x2, y2), then you consume |x1-x2|+|y1-y2|-1
energies. Energy can be negative.

However, in a jump, if you start position and end position has same numbers S, then you can increase the energy value by S.

Give me the maximum energy you can get. Notice that you have to go each grid exactly once and you don’t have to play exactly K times.
 
Input
The first line is an integer T, stands for the number of the text cases.

Then T cases followed and each case begin with three numbers N, M and K. Means there are N rows and M columns, you have K times to play.

Then N lines follow, each line is a string which is made up by M numbers.

The grids only contain numbers from 0 to 9.

(T<=100, N<=10,M<=10,K<=100)
 
Output
Each case, The first you should output “Case x : ”,(x starting at 1),then output The maximum number of energy value you can get. If you can’t reach every grid in no more than K times, just output -1.
 
Sample Input
5
1 5 1
91929
1 5 2
91929
1 5 3
91929
3 3 3
333
333
333
3 3 2
333
333
333
 
Sample Output
Case 1 : 0
Case 2 : 15
Case 3 : 16
Case 4 : 18
Case 5 : -1

题目大意:给出一个n行m列的矩阵,每个坐标上都有一个权值,可以最多走k次(注意不是k步),每一次行走可以任意选择起点(必须是没有走过的点),然后可以向右或者向下走任意的步数,每一步可以跨越任意的格数,前提是满足题目的限制条件,每走一步耗费的能量是两坐标的曼哈顿距离-1,加入走的当前点的权值和前一步的权值一样,可以获得该权值的能量,问在k次行走内,走完每一格且仅走一次,最多可以获得多少能量:这道题目主要是建图,k次的建图非常巧妙。

官方题解:

最小K路径覆盖的模型,用费用流或者KM算法解决,构造二部图,X部有N*M个节点,源点向X部每个节点连一条边,流量1,费用0,Y部有N*M个节点,每个节点向汇点连一条边,流量1,费用0,如果X部的节点x可以在一步之内到达Y部的节点y,那么就连边x->y,费用为从x格子到y格子的花费能量减去得到的能量,流量1,再在X部增加一个新的节点,表示可以从任意节点出发K次,源点向其连边,费用0,流量K,这个点向Y部每个点连边,费用0,流量1,最这个图跑最小费用最大流,如果满流就是存在解,反之不存在,最小费用的相反数就是可以获得的最大能量

可以这样考虑,首先建立一个二分图,在x部内的可以到达y部的点建边<u,v>;首先求得该二部图的最小路径覆盖=节点总数-最大流;(最小路径覆盖:用最少的路径覆盖住所有的节点,且每个节点只能在一条路径上),加入k值小于最小的路径数目,那么肯定是在k次之内是不可能完成任务的。

所以这样建图之后求得是原先的最大流+k,若最大流+k<n*m则无解,输出-1,否则求出的最小费用的相反数就是最大能量。

程序;

#include"stdio.h"
#include"string.h"
#include"iostream"
#include"map"
#include"string"
#include"queue"
#include"stdlib.h"
#include"math.h"
#define M 333
#define eps 1e-10
#define inf 1000000000
#define mod 2333333
using namespace std;
struct node
{
int u,v,w,cost,next;
}edge[M*M*3];
int t,head[M],dis[M],use[M],pre[M],Max_flow,Min_cost,top[M],q[M],work[M];
void init()
{
t=0;
memset(head,-1,sizeof(head));
}
void add(int u,int v,int w,int cost)
{
edge[t].u=u;
edge[t].v=v;
edge[t].w=w;
edge[t].cost=cost;
edge[t].next=head[u];
head[u]=t++; edge[t].u=v;
edge[t].v=u;
edge[t].w=0;
edge[t].cost=-cost;
edge[t].next=head[v];
head[v]=t++;
}
int min_flow(int S,int T)
{
int ans=0;
Max_flow=0;
while(1)
{
int i;
queue<int>q;
for(i=0;i<=T+1;i++)
dis[i]=inf;
dis[S]=0;
memset(use,0,sizeof(use));
memset(pre,-1,sizeof(pre));
q.push(S);
while(!q.empty())
{
int u=q.front();
use[u]=0;
q.pop();
for(i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(edge[i].w&&dis[v]>dis[u]+edge[i].cost)
{
dis[v]=dis[u]+edge[i].cost;
pre[v]=i;
if(!use[v])
{
use[v]=1;
q.push(v);
}
}
}
}
if(dis[T]==inf)
break;
int Min=inf+1;
for(i=pre[T];i!=-1;i=pre[edge[i].u])
{
Min=min(Min,edge[i].w);
}
for(i=pre[T];i!=-1;i=pre[edge[i].u])
{
edge[i].w-=Min;
edge[i^1].w+=Min;
}
Max_flow+=Min;
ans+=Min*dis[T];
}
return ans;
}
int num[22][22],mp[22][22];
char Mp[22][22];
int main()
{
int T,kk=1;
scanf("%d",&T);
while(T--)
{
int n,m,k,i,j,r;
scanf("%d%d%d",&n,&m,&k);
int cnt=0;
init();
for(i=1;i<=n;i++)
{
scanf("%s",Mp[i]);
for(j=1;j<=m;j++)
{
mp[i][j]=Mp[i][j-1]-'0';
num[i][j]=++cnt;
}
}
for(i=1;i<=m*n;i++)
{
add(0,i,1,0);
add(i+m*n,m*n*2+1,1,0);
}
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
int Cost;
for(r=j+1;r<=m;r++)
{
if(mp[i][j]==mp[i][r])
Cost=r-j-1-mp[i][j];
else
Cost=r-j-1;
add(num[i][j],num[i][r]+m*n,1,Cost);
}
for(r=i+1;r<=n;r++)
{
if(mp[i][j]==mp[r][j])
Cost=r-i-1-mp[i][j];
else
Cost=r-i-1;
add(num[i][j],num[r][j]+m*n,1,Cost);
}
}
}
for(i=n*m+1;i<=m*n*2;i++)
add(m*n*2+2,i,1,0);
add(0,m*n*2+2,k,0);
Min_cost=min_flow(0,m*n*2+1);
printf("Case %d : ",kk++);
if(Max_flow!=n*m)
{
printf("-1\n");
continue;
}
printf("%d\n",-Min_cost);
}
}

网络费用流-最小k路径覆盖的更多相关文章

  1. HDU 4862 Jump(最小K路径覆盖)

    输入一个n×m网格图,每个结点的值为0-9,可以从任意点出发不超过k次,走完每个点且仅访问每个结点一次,问最终的能量最大值.不可全部走完的情况输出-1. 初始能量为0. 而结点(x,y)可以跳跃到结点 ...

  2. [luoguP2765] 魔术球问题(最大流—最小不相交路径覆盖)

    传送门 枚举球的个数 num 如果 i < j && (i + j) 是完全平方数,那么 i -> j' 连一条边 再加一个超级源点 s,s -> i 再加一个超级汇 ...

  3. hdu 4862 KM算法 最小K路径覆盖的模型

    http://acm.hdu.edu.cn/showproblem.php?pid=4862 选t<=k次,t条路要经过全部的点一次而且只一次. 建图是问题: 我自己最初就把n*m 个点分别放入 ...

  4. Air Raid POJ - 1422 【有向无环图(DAG)的最小路径覆盖【最小不相交路径覆盖】 模板题】

    Consider a town where all the streets are one-way and each street leads from one intersection to ano ...

  5. P2172 [国家集训队]部落战争 二分图最小不相交路径覆盖

    二分图最小不相交路径覆盖 #include<bits/stdc++.h> using namespace std; ; ; ; ], nxt[MAXM << ], f[MAXM ...

  6. 【洛谷2469/BZOJ1927】[SDOI2010]星际竞速(费用流/最小路径覆盖)

    题目: 洛谷2469 分析: 把题目翻译成人话:给一个带边权的DAG,求一个路径覆盖方案使路径边权总和最小.从点\(i\)开始的路径需要额外加上\(A_i\)的权值. 回xian忆chang一xue下 ...

  7. POJ Air Raid 【DAG的最小不相交路径覆盖】

    传送门:http://poj.org/problem?id=1422 Air Raid Time Limit: 1000MS   Memory Limit: 10000K Total Submissi ...

  8. CF802C Heidi and Library hard 费用流 区间k覆盖问题

    LINK:Heidi and Library 先说一下简单版本的 就是权值都为1. 一直无脑加书 然后发现会引起冲突,可以发现此时需要扔掉一本书. 扔掉的话 可以考虑扔掉哪一本是最优的 可以发现扔掉n ...

  9. [模板]网络最大流 & 最小费用最大流

    我的作业部落有学习资料 可学的知识点 Dinic 模板 #define rg register #define _ 10001 #define INF 2147483647 #define min(x ...

随机推荐

  1. apt-get强制使用Ipv4

    sudo apt-get -o Acquire::ForceIPv4=true update 永久解决办法: 创建文件 /etc/apt/apt.conf.d/99force-ipv4 加入代码: A ...

  2. 【转】DirectorySearcher.Filter属性说明

    DirectorySearcher.Filter属性扩充申明 DirectorySearcher mySearcher = new DirectorySearcher(entryOU, "( ...

  3. 【转】C# 二维码生成

    /// <summary> /// 含有QR码的描述类和包装编码和渲染 /// </summary> public class QRCodeHelper { /// <s ...

  4. imx6 spi分析

    /************************************************************************** *本文主要跟踪imx6 spi设备和驱动的注册过 ...

  5. wd mycloud nas新玩法

    最近家里的小米路由器坏了,主要是硬盘读取不出,小米之家也无能为力,本想继续在小米之家买个小米路由器,后来了解到了nas,于是想折腾下.我的nas型号是wd mycloud,3TB内置硬盘.功能:可以组 ...

  6. php HTML安全过滤

    /*HTML安全过滤*/ function _htmtocode($content) { $content = str_replace('%','%‎',$content); $content = s ...

  7. Oracle查询优化-插入、更新与删除

    --插入.更新与删除 --1.插入新纪录 --1.1.建立测试表 DROP TABLE TEST; CREATE TABLE TEST( C1 ) DEFAULT '默认1', C2 ) DEFAUL ...

  8. TTreeView TTreeNodes TTreeNode

    TTreeView 填写 TTreeView 的内容一般是这样开始的(下图), 不过我觉得最好习惯用动态建立. 打个比方: 譬如 TreeView 是一个军营的"营部"! 这里会有 ...

  9. CentOS7.1 Liberty云平台之Dashboard篇(7)

    控制节点: 一.安装及配置Dashboard 1.安装dashboard相关包 yum install openstack-dashboard 2.配置/etc/openstack-dashboard ...

  10. 超全面的JavaWeb笔记day11<JSP&Session&Cookie&HttpSession>

    1.JSP 2.回话跟踪技术 3.Cookie 4.HttpSession JSP入门 1 JSP概述 1.1 什么是JSP JSP(Java Server Pages)是JavaWeb服务器端的动态 ...