hdu 2686 费用流 / 双线程DP
题意:给一个方阵,求从左上角出到右下角(并返回到起点),经过每个点一次不重复,求最大获益(走到某处获得改点数值),下来时每次只能向右或向下,反之向上或向左。
俩种解法:
1 费用流法:思路转化:从左上角流出2的流量,(表示走俩条路),归于右下角,可以走就有边(右和下),权为负的费用,源点连起点,汇点连终点,流量为2. 除源汇外所有点一分为2,Y向X对应点有流量1的边,之前边为X到Y的(原图),这样处理解决每个点只最多走一次(除了源汇外)(X部只出,Y部要出必先回到X对应点)。跑最小费用最大流即可。
2:dp法:(感谢XX大牛的提示)俩个点同时走,走了第K步状态:为x1,y1;x2,y2, 由于(x1+y1=k,x2+y2=k),状态压缩为3维,每个状态表示当前这步俩个点的横左边。
dp[k][x1][x2]=max(dp[k-1][x1][x2],dp[k-1][x1][x2-1],dp[k-1][x1-1][x2],dp[k-1][x1-1][x2-1])
方法1:
#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
const int inf=0x3f3f3f3f;
int a[50][50];
int nume=0;int e[50000][4];int head[2000];
int n;
void inline adde(int i,int j,int c,int w)
{
e[nume][0]=j;e[nume][1]=head[i];head[i]=nume;
e[nume][2]=c;e[nume++][3]=w;
e[nume][0]=i;e[nume][1]=head[j];head[j]=nume;
e[nume][2]=0;e[nume++][3]=-w;
}
int inq[2000];int pre[2000];int prv[2000];
int d[2000];
bool spfa(int &sum)
{
for(int i=0;i<=2*n*n+2;i++)
{
inq[i]=0;
d[i]=inf;
}
queue<int>q;
q.push(2*n*n);
inq[2*n*n]=1;
d[2*n*n]=0;
while(!q.empty())
{
int cur=q.front();
q.pop();
inq[cur]=0;
for(int i=head[cur];i!=-1;i=e[i][1])
{
int v=e[i][0];
if(e[i][2]>0&&d[cur]+e[i][3]<d[v])
{
d[v]=d[cur]+e[i][3];
pre[v]=i;
prv[v]=cur;
if(!inq[v])
{
q.push(v);
inq[v]=1;
}
}
}
}
if(d[2*n*n+1]==inf)return 0;
int cur=2*n*n+1;int minf=inf;
while(cur!=2*n*n)
{
minf=e[pre[cur]][2]<minf?e[pre[cur]][2]:minf;
cur=prv[cur];
}
cur=2*n*n+1;
while(cur!=2*n*n)
{
e[pre[cur]][2]-=minf;
e[pre[cur]^1][2]+=minf;
cur=prv[cur];
}
sum+=minf*d[2*n*n+1];
return 1;
} int mincost()
{
int sum=0;
while(spfa(sum));
return sum;
}
void init()
{
nume=0;
memset(head,-1,sizeof(head));
}
int main()
{
while(~scanf("%d",&n))
{
init();
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
scanf("%d",&a[i][j]);
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
if(i+1<n)
adde(i*n+j,(i+1)*n+j+n*n,1,-a[i+1][j]);
if(j+1<n)
adde(i*n+j,i*n+j+1+n*n,1,-a[i][j+1]);
}
for(int i=0;i<n*n;i++)
{
adde(i+n*n,i,1,0);
}
adde(2*n*n,0,2,0);
adde(2*n*n-1,2*n*n+1,2,0);
int ans=-mincost();
ans+=a[0][0];
ans-=a[n-1][n-1];
printf("%d\n",ans);
}
return 0;
}
方法2
;
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int a[50][50];
int dp[80][50][50];
int max(int x,int y,int z,int t)
{
if(x>=y&&x>=z&&x>=t)return x;
if(y>=x&&y>=z&&y>=t)return y;
if(z>=x&&z>=y&&z>=t)return z;
return t;
}
int main()
{
int n;
while(~scanf("%d",&n))
{
memset(dp,0,sizeof(dp));
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
scanf("%d",&a[i][j]);
dp[0][0][0]=a[0][0];
dp[1][0][1]=a[0][1]+a[0][0]+a[1][0]; for(int k=1;k<=2*n-2;k++)
{
for(int x1=0;x1<=k&&x1<n;x1++)
{
for(int x2=0;x2<=k&&x2<n;x2++)
{
if(x1!=x2)
{
if(x1>0&&x2>0)
dp[k][x1][x2]=max(dp[k-1][x1][x2],dp[k-1][x1][x2-1],dp[k-1][x1-1][x2],dp[k-1][x1-1][x2-1]);
else if(x1==0&&x2>0)
{
dp[k][x1][x2]=max(dp[k-1][x1][x2],dp[k-1][x1][x2-1],0,0);
}
else
{
dp[k][x1][x2]=max(dp[k-1][x1][x2],dp[k-1][x1-1][x2],0,0);
}
dp[k][x1][x2]+=(a[x1][k-x1]+a[x2][k-x2]); }
}
}
}
int ans=dp[2*n-3][n-2][n-1]+a[n-1][n-1];
cout<<ans<<endl;
}
return 0;
}
hdu 2686 费用流 / 双线程DP的更多相关文章
- [Swust OJ 1084]--Mzx0821月赛系列之情书(双线程dp)
题目链接:http://acm.swust.edu.cn/problem/1084/ Time limit(ms): 1000 Memory limit(kb): 65535 Descriptio ...
- hdu 5045 费用流
滚动建图,最大费用流(每次仅仅有就10个点的二分图).复杂度,m/n*(n^2)(n<=10),今年网络赛唯一网络流题,被队友状压DP秒了....难道网络流要逐渐退出历史舞台???.... #i ...
- Going Home HDU - 1533 费用流
http://acm.hdu.edu.cn/showproblem.php?pid=1533 给一个网格图,每两个点之间的匹配花费为其曼哈顿距离,问给每个的"$m$"匹配到一个&q ...
- HDU 3376 费用流 Matrix Again
题意: 给出一个n × n的矩阵,每个格子中有一个数字代表权值,找出从左上角出发到右下角的两条不相交的路径(起点和终点除外),使得两条路径权值之和最大. 分析: 如果n比较小的话是可以DP的,但是现在 ...
- nyist 61 传纸条 nyist 712 探 寻 宝 藏(双线程dp问题)
http://acm.nyist.net/JudgeOnline/problem.php?pid=61 http://acm.nyist.net/JudgeOnline/problem.php?pid ...
- 传纸条(一)(双线程dp)
传纸条(一) 时间限制:2000 ms | 内存限制:65535 KB 难度:5 描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行 ...
- hdu 4406 费用流
这题问题就是当前时刻究竟选择哪门课程,易知选择是和分数有关的,而且是一个变化的权值,所以能够用拆点的方式,把从基础分到100分都拆成点.但若这样拆点的话,跑费用流时就必须保证顺序.这样就麻烦了..观察 ...
- CF739E Gosha is hunting(费用流/凸优化dp)
纪念合格考爆炸. 其实这个题之前就写过博客了,qwq但是不小心弄丢了,所以今天来补一下. 首先,一看到球的个数的限制,不难相当用网络流的流量来限制每个球使用的数量. 由于涉及到最大化期望,所以要使用最 ...
- hdu 1853 (费用流 拆点)
// 给定一个有向图,必须用若干个环来覆盖整个图,要求这些覆盖的环的权值最小. 思路:原图每个点 u 拆为 u 和 u' ,从源点引容量为 1 费用为 0 的边到 u ,从 u' 引相同性质的边到汇点 ...
随机推荐
- 数据库_6_SQL基本操作——库操作
SQL基本操作——库操作:对数据库的增删改查 一.新增数据库(创建) 基本语法:create database 数据库名字 [库选项]: 库选项用来约束数据库,分为两个选项:1.字符集设定:chars ...
- 在64位的linux中运行32位的应用程序
常规做法,先添加32bit架构: sudo dpkg --add-architecture i386 sudo apt-get update sudo apt-get install libc6:i3 ...
- PAT (Basic Level) Practise (中文)- 1026. 程序运行时间(15)
PAT (Basic Level) Practise (中文)- 1026. 程序运行时间(15) http://www.patest.cn/contests/pat-b-practise/10 ...
- 快速幂&&矩阵快速幂
快速幂 题目链接:https://www.luogu.org/problemnew/show/P1226 快速幂用了二分的思想,即将\(a^{b}\)的指数b不断分解成二进制的形式,然后相乘累加起来, ...
- https 调用验证失败 peer not authenticated
https 调用验证失败 peer not authenticated 报错日志: Caused by: javax.net.ssl.SSLPeerUnverifiedException: peer ...
- [图文] Fedora 28 使用 Virt-Manager 制作并优化QCOW2镜像——Windows 10 1709
实验说明: 云计算的发展使得桌面上云,windows 10就必不可少,这一章就如何制作QCOW2镜像文件并优化进行说明. 实验环境: 宿主机系统 :Fedora 28 WorkStation 虚拟 ...
- Web框架之Django_06 模型层了解(F查询、Q查询、事务、update和save、only和defer、choice属性、bulk_create)
摘要: F查询 Q查询 事务 一.F查询 在上面所有的例子中,我们构造的过滤器都只是将字段值与某个我们自己设定的常量做比较.如果我们要对两个字段的值做比较,那该怎么做呢?Django 提供 F() 来 ...
- ACM训练联盟周赛 G. Teemo's convex polygon
65536K Teemo is very interested in convex polygon. There is a convex n-sides polygon, and Teemo co ...
- Objective-c 实例变量的访问级别
在C#和JAVA中无论是method还是variable都有严格的访问级别控制,那么在object-c中对访问级别的使用非常稀少,原因可能是因为在method上没有访问级别的语法,单单控制变量没有什么 ...
- [android篇]声明权限
要实施您自己的权限,必须先使用一个或多个 <permission> 元素在 AndroidManifest.xml 中声明它们. 实际上,在开发过程中,当我们使用了某些系统特性的功能,且此 ...