hdu 5303 DP(离散化,环形)

题目无法正常粘贴,地址:http://acm.hdu.edu.cn/showproblem.php?pid=5303

大意是给出一个环形公路,和它的长度,给出若干颗果树的位置以及树上的果子个数。

起点为0,背包大小为K,求最小走多少距离能摘完所有的果子并回到起点。

观察得知,公路长度L虽然上界10^9,但果子总和最多10^5,还是可做的。

显然如果想回家时在左半边肯定逆时针返回更近,在右边同理顺时针更近。

所有最优解可能是有饶了一整圈的路或是只在左/右两边往返得到。

由于背包的大小限制每次取果子的个数,为了方便处理数据,我们不妨将果子做离散化处理,存进x数组中(x[i]即第i个果子的位置);

我们可以将左/右两边的果子按距离远点的距离排序放入两个l/r容器中。

之后dp1[i]表示从原点顺时针出发取得第i个果子再返回原点所需时间的一半(保存为一半的距离方便计算),dp2同理.

处理完之后假设不饶圈,ans=dp1[l.size()]+dp2[r.size()];

接着我们枚举绕圈的点即可,我们枚举绕圈时取得的果子数目,[0,K],而且不能超出左边的果子数,所以[0,min(K,l.size())];

对于此时,右边

#include<bits/stdc++.h>#include<algorithm>
using namespace std;
#define LL long long
LL x[100005];
LL dp1[100005],dp2[100005];
vector<LL> l,r;
int main()
{
    int N,M,K,L,T;
    int i,j;
    LL X,A;
    scanf("%d",&T);
    while(T--){int cnt=0; LL ans;
    l.clear(); r.clear();
        scanf("%d %d %d",&L,&N,&K);
        for(i=0;i<N;++i){
            scanf("%lld%lld",&X,&A);
            for(j=1;j<=A;++j)
            x[++cnt]=(LL)X;
        }
        for(i=1;i<=cnt;++i){
           if(2*x[i]<L) l.push_back(x[i]);
           else r.push_back(L-x[i]);
        }int szl=l.size(),szr=r.size();
        sort(l.begin(),l.end());
        sort(r.begin(),r.end());
        for(i=0;i<szl;++i){

        dp1[i+1]=(i+1<=K?l[i]:dp1[i+1-K]+l[i]);
        }
        for(i=0;i<szr;++i){
        dp2[i+1]=(i+1<=K?r[i]:dp2[i + 1-K]+r[i]);
        }
        ans=(dp1[szl]+dp2[szr])*2;
        for(i=0;i<=szl&&i<=K;++i){
                int p1=szl-i;
                int p2=max(0,szr-(K-i));
            ans=min(ans,2*(dp1[p1]+dp2[p2])+L);

        }
        printf("%lld\n",ans);
    }
    return 0;
}
时间: 2024-10-06 04:25:07

hdu 5303 DP(离散化,环形)的相关文章

HDU 5303 dp

一个环上有n个苹果树,每个树上有ai个苹果,你有一个容量为k的篮子,装满苹果后要回到起点清空篮子,问你从起点出发,摘完所有苹果所走的最短路程. 苹果最多有100000个 使用两个DP数组,dp[0][i]表示顺时针取i个苹果的最短路程,dp[1][i]表示逆时针取i个苹果的最短路程 ans=Min(dp[0][i],dp[1][sum-i]); #include "stdio.h" #include "string.h" #include "algorit

HDU 4832(DP+计数问题)

HDU 4832 Chess 思路:把行列的情况分别dp求出来,然后枚举行用几行,竖用几行,然后相乘累加起来就是答案 代码: #include <stdio.h> #include <string.h> #include <iostream> using namespace std; typedef long long ll; const ll MOD = 9999991; const int N = 1005; int t, n, m, k, x, y; ll dp1

hdu 3944 dp?

DP? Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 128000/128000 K (Java/Others)Total Submission(s): 1804    Accepted Submission(s): 595 Problem Description Figure 1 shows the Yang Hui Triangle. We number the row from top to bottom 0,1,2,-a

POJ - 3666 Making the Grade(dp+离散化)

Description A straight dirt road connects two fields on FJ's farm, but it changes elevation more than FJ would like. His cows do not mind climbing up or down a single slope, but they are not fond of an alternating succession of hills and valleys. FJ

Codeforces 13C Sequence --DP+离散化

题意:给出一个 n (1 <= n <= 5000)个数的序列 .每个操作可以把 n 个数中的某一个加1 或 减 1.问使这个序列变成非递减的操作数最少是多少 解法:定义dp[i][j]为将前i个数变为以j为结尾的非递减序列的最少操作次数. 则有: dp[i][j] = min(dp[i][j], min(dp[i][k]) + Cost(原来第i个位置上的数转换到j))  (1 <= k <= j) 即前i个数以j结尾的状态可以由前i-1个数以小于等于j的k结尾的状态转移过来,取

hdu 5389 dp类似背包

http://acm.hdu.edu.cn/showproblem.php?pid=5389 Problem Description Zero Escape, is a visual novel adventure video game directed by Kotaro Uchikoshi (you may hear about ever17?) and developed by Chunsoft. Stilwell is enjoying the first chapter of this

hdu 1025 dp 最长上升子序列

1 //Accepted 4372 KB 140 ms 2 //dp 最长上升子序列 nlogn 3 #include <cstdio> 4 #include <cstring> 5 #include <iostream> 6 using namespace std; 7 const int imax_n = 500005; 8 int dp[imax_n]; 9 int d[imax_n]; 10 int a[imax_n]; 11 int n; 12 int len

HDU 5928 DP 凸包graham

给出点集,和不大于L长的绳子,问能包裹住的最多点数. 考虑每个点都作为左下角的起点跑一遍极角序求凸包,求的过程中用DP记录当前以j为当前末端为结束的的最小长度,其中一维作为背包的是凸包内侧点的数量.也就是 dp[j][k]代表当前链末端为j,其内部点包括边界数量为k的最小长度.这样最后得到的一定是最优的凸包. 然后就是要注意要dp[j][k]的值不能超过L,每跑一次凸包,求个最大的点数量就好了. 和DP结合的计算几何题,主要考虑DP怎么搞 /** @Date : 2017-09-27 17:27

HDU 4901 DP背包

给你n个数,问你将数分成两个数组,S,T ,T 中所有元素的需要都比S任意一个大,问你S中所有元素进行 XOR 操作和 T 中所有元素进行 &操作值相等的情况有多少种. DP背包思路 dpa[i][j][0]  表示从左开始到i,不取i,状态为j的方案数 dpa[i][j][1]  表示从作开始到i,取i,状态为j的方案数 dpb[i][j]      表示从右开始到i,状态为j的方案数 因为S集合一定在T集合的左边,那么可以枚举集合的分割线,并且枚举出的方案要保证没有重复,如果要保证不重复,只