ZOJ-3524 拓扑排序+完全背包(好题)
题意:在一个DAG上,主角初始有W钱起点在s点,每个点有一个代价wi和价值vi,主角从起点走到某一点不能回头走,一路上可以买东西(一个点的东西可以买无限次),且体力消耗为身上负重*路径长度。主角可以在任意一点停止旅程,问在获得最大价值情况下体力消耗最小。
解法:第一次遇到这类型的题,看大佬题解,这里说下自己的理解。首先主角在DAG上走且不能回头,那么比较明显让我们想到按拓扑排序顺序进行dp,这是正确的但是代码实现可能不那么容易想:我们首先对DAG进行拓扑排序求出它的拓扑序V,按照拓扑序进行完全背包的DP,这里要注意一点就是因为主角是有起点的,所以有的地方是根本到达不到的,我们可以用个vis数组来代表主角能到达的点,能动到达的点才能DP。DP思路是:设计状态dp[x][j]为走到x点,容量为j的最大价值,同时tp[x][j]为最大价值为dp[x][j]时候的最小体力消耗,那么我们到一个新点,我们先对这个的的物品做完全背包,然后用这个点x去更新x的下一步y的状态(这也是拓扑序DP的核心)。DP的同时更新答案即可。
这里提出一个问题就是为什么在两个限制下要求的答案dp状态不用设计成三维的呢?设计成两位状态能保证是在容量限制下最大价值且在最大价值下的最小消耗吗?这个问题蒟蒻一开始想不通,这是因为答案只要最好的。当然也可以把状态设计成例如dp[x][j][k]代表到x点容量为j价值为k的最小体力消耗,但是注意到因为题目要求的是最大价值下的最小消耗,所以这个状态的除了dp[x][j][Maxv](Maxv是x点容量j的最大价值)是有用的,其他的都是没用的dp[x][j][val] (val<Maxv)。因为此时容量已经确定,那么以后的状态在这些状态中容量相等的肯定选价值最大的,其他价值小的不会对后面结果造成任何影响。
除此以为这道题还有一些细节,不懂的建议看代码理解:
#include<bits/stdc++.h>
using namespace std;
const int N=+;
const int M=6e4+;
int n,m,W,s,Maxv,Mint,deg[N],w[N],v[N];
vector<int> V; int cnt=,head[N],nxt[M],to[M],len[M];
void add_edge(int x,int y,int z) {
nxt[++cnt]=head[x]; to[cnt]=y; len[cnt]=z; head[x]=cnt;
} queue<int> q;
void toposort() {
for (int i=;i<=n;i++) if (deg[i]==) q.push(i);
while (!q.empty()) {
int x=q.front(); q.pop();
V.push_back(x);
for (int i=head[x];i;i=nxt[i]) {
int y=to[i];
if (--deg[y]==) q.push(y);
}
}
} bool vis[N];
int dp[N][],tp[N][];
void solve() {
memset(dp,,sizeof(dp));
memset(tp,0x3f,sizeof(tp));
memset(vis,,sizeof(vis)); vis[s]=;
dp[s][]=; tp[s][]=;
for (int i=;i<V.size();i++) {
if (!vis[V[i]]) continue;
int x=V[i];
for (int j=w[x];j<=W;j++)
if (dp[x][j-w[x]]+v[x]>dp[x][j]) dp[x][j]=dp[x][j-w[x]]+v[x],tp[x][j]=tp[x][j-w[x]];
else if (dp[x][j-w[x]]+v[x]==dp[x][j]) tp[x][j]=min(tp[x][j],tp[x][j-w[x]]);
for (int j=head[x];j;j=nxt[j]) {
int y=to[j];
vis[y]=;
for (int k=;k<=W;k++)
if (dp[x][k]>dp[y][k]) {
dp[y][k]=dp[x][k];
tp[y][k]=tp[x][k]+len[j]*k;
} else if (dp[y][k]==dp[x][k]) {
int tmp=tp[x][k]+len[j]*k;
tp[y][k]=min(tp[y][k],tmp);
}
}
for (int j=;j<=W;j++)
if (dp[x][j]>Maxv || dp[x][j]==Maxv && tp[x][j]<Mint) {
Maxv=dp[x][j]; Mint=tp[x][j];
}
}
} int main()
{
while (scanf("%d%d%d%d",&n,&m,&W,&s)==) {
for (int i=;i<=n;i++) scanf("%d%d",&w[i],&v[i]);
memset(deg,,sizeof(deg));
cnt=; memset(head,,sizeof(head));
for (int i=;i<=m;i++) {
int x,y,z; scanf("%d%d%d",&x,&y,&z);
add_edge(x,y,z); deg[y]++;
}
V.clear(); toposort();
Maxv=; Mint=0x3f3f3f3f;
solve();
printf("%d\n",Mint);
}
return ;
}
ZOJ-3524 拓扑排序+完全背包(好题)的更多相关文章
- zoj 3524(拓扑排序+多重背包)(好题)
http://blog.csdn.net/woshi250hua/article/details/7824773 题目大意:从前有n座山,山里都有一座庙,庙里都有一个老和尚,老和尚专送纪念品,每个纪念 ...
- Crazy Shopping(拓扑排序+完全背包)
Crazy Shopping(拓扑排序+完全背包) Because of the 90th anniversary of the Coherent & Cute Patchouli (C.C. ...
- ZOJ 4124 拓扑排序+思维dfs
ZOJ - 4124Median 题目大意:有n个元素,给出m对a>b的关系,问哪个元素可能是第(n+1)/2个元素,可能的元素位置相应输出1,反之输出0 省赛都过去两周了,现在才补这题,这题感 ...
- E - Ingredients 拓扑排序+01背包
题源:https://codeforces.com/gym/101635/attachments 题意: n行,每行给定字符串s1,s2,s3代表一些菜谱名.s2和s3是煮成是的必要条件,然后给出c和 ...
- HDU 3342 -- Legal or Not【裸拓扑排序 &&水题 && 邻接表实现】
Legal or Not Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tot ...
- 第十二届湖南省赛 (B - 有向无环图 )(拓扑排序+思维)好题
Bobo 有一个 n 个点,m 条边的有向无环图(即对于任意点 v,不存在从点 v 开始.点 v 结束的路径). 为了方便,点用 1,2,…,n 编号. 设 count(x,y) 表示点 x 到点 y ...
- C#LeetCode刷题-拓扑排序
拓扑排序篇 # 题名 刷题 通过率 难度 207 课程表 40.0% 中等 210 课程表 II 39.8% 中等 329 矩阵中的最长递增路径 31.0% 困难
- poj 3687 Labeling Balls(拓扑排序)
题目:http://poj.org/problem?id=3687题意:n个重量为1~n的球,给定一些编号间的重量比较关系,现在给每个球编号,在符合条件的前提下使得编号小的球重量小.(先保证1号球最轻 ...
- [ACM] POJ 3687 Labeling Balls (拓扑排序,反向生成端)
Labeling Balls Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10161 Accepted: 2810 D ...
随机推荐
- CocoaPods CDN: trunk Repo update failed
问题 今天升级 CocoaPods 到 1.8.4 版本但是随即问题就来了, 执行 pod install 下载库时,出现错误 解决 在 Podfile 加上 source ‘https://gith ...
- Provider
import React from 'react';import PropTypes from 'prop-types'; class Provider extends React.Component ...
- macos系统安装nginx
MacOS系统安装软件: macos系统下没有yum和apt-get命令,要安装软件需要使用homebrew. 1.安装homebrew: 安装:/usr/bin/ruby -e "$(cu ...
- 解决error: Microsoft Visual C++ 14.0 is required 问题
1.https://964279924.ctfile.com/fs/1445568-239446865 2.重新安装 .Net framework 更高的版本:https://support.micr ...
- JQuery-跑马灯(文字无缝向上翻动-封装)
转载自他人:https://blog.csdn.net/z69183787/article/details/12857587 (function($){ $.fn.extend({ &qu ...
- NFA 、DFA 简述
转载请注明出处 https://www.cnblogs.com/majianming/p/11823697.html 目前常见的正则表达引擎总体分为2种,DFA (确定型有穷状态自动机) 和 NFA ...
- 【leetcode】909. Snakes and Ladders
题目如下: 解题思路:天坑题,不在于题目多难,而是要理解题意.题目中有两点要特别注意,一是“You choose a destination square S with number x+1, x+2 ...
- 【Shell】ps -ef 和ps aux
两者没太大差别 追溯到Unix系统中的两种风格,System V风格和BSD 风格,ps aux最初用到Unix Style中,而ps -ef被用在System V Style中,两者输出略有不同.现 ...
- Linux的软件包管理
此博客的环境任意. 主题Linux的软件包管理 一软件管理工具 1编译安装 2rpm包管理 3yum管理 二软件运行和编译 1ABI 应用程序的二进制接口 ABI:Appl ...
- 记一次引入less自己坑自己的坑....
loader里该有的loader都有了,但是在npm run dev的时候,就是找不到less文件. 最后,才发现,用了postcss-loader,但是去package.json里查了一下,并没有安 ...