博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
旅行线路
阅读量:7005 次
发布时间:2019-06-27

本文共 1658 字,大约阅读时间需要 5 分钟。

【题目描述】

贝西经营着一家旅行社,一天贝西带着几队游客沿着亚马逊河旅行,河的两边分布着一些景点,每个景点都对应着一个观赏值。景点间由一些穿过河流的道路相连(位于河流同一侧的景点间没有直接道路相连),贝西想要设计游客的旅行线路,使得该线路经过的景点的总的观赏值最大。
但是,贝西可能同时带着几个旅行团,贝西希望它给安排的旅行线路不能相交。
两条线路 (a <-> x) 和 (b <-> y) 出现如下情况之一就算相交:
if(a < b and y < x) or (a > b and x < y) or (a = b and x = y).
帮助贝西找出最佳旅行线路,贝西可以从任意景点开始,在任意景点结束。
【输入格式】
第一行,三个空格间隔的整数N (1 <= N <= 40,000), M (1 <=M <= 40,000), and R (0<= R <= 100,000) 。N表示河岸左边的景点数,M表示河岸右边的景点数,R表示道路的条数
接下来N行,每行一个整数,表示河岸左边对应景点的观赏值。
接下来M行,每行一个整数,表示河岸右边对应景点的观赏值。
接下来R行,每行两个空格间隔的整数X,Y,表示左岸的X号景点与右岸的Y号景点间有道路直接相连。
(0 <= 观赏值<= 40,000)
【输出格式】
一个整数,表示所求最大观赏值。
【样例输入】
3 2 4
1
1
5
2
2
1 1
2 1
3 1
2 2
【样例输出】
8
【分析】
首先可以看出这题不能用贪心解决。
一种比较明显的思路就是双重循环枚举两个点后DP,但是更明显的是这样做的时间复杂度根本不能承受。
联想到克鲁斯卡尔算法与普利姆算法的区别,我们想到以边作为状态。首先要排序(去除后效性),然后设f1[i]表示左边以i结尾的最大收益,f2[i]表示右边以i结尾的最大收益,状态转移方程就很明显了。
转移的时候注意用临时变量存储。

#include
#include
#include
#include
using namespace std;#define maxn 40005#define maxe 100005typedef long long LL;typedef pair
pii;int n,m,k;LL a[maxn],b[maxn],f1[maxn],f2[maxn];pii e[maxe];int main(){ scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=m;i++) scanf("%d",&b[i]); for(int i=1;i<=k;i++) scanf("%d%d",&e[i].first,&e[i].second); sort(e+1,e+k+1); memcpy(f1,a,sizeof(a)); memcpy(f2,b,sizeof(b)); for(int i=k;i>=1;i--) { int u=e[i].first,v=e[i].second; LL va=a[u]+f2[v]; LL vb=b[v]+f1[u]; f1[u]=max(f1[u],va); f2[v]=max(f2[v],vb); } int ans=0; for (int i=1;i<=n;i++) if (ans

转载于:https://www.cnblogs.com/JRX2015U43/p/6533496.html

你可能感兴趣的文章