HDU 5303

    xiaoxiao2021-03-25  93

    HDU 5303 题意是在一个圆上,有n颗苹果树,相对起点的顺时针距离为xi,每棵树上有ai个苹果。现在带上一个容量为K的篮子,从起点出发,问将所有苹果收回来至少要花多少时间? 显然,从起点出发,不论从从左或是右,在不跨过终点m时,摘到K个苹果后最佳的路径是原路返回。跨过了中点m,那么最佳路径是走一圈回到起点。显然,我们至多只会跨过m一次,因为跨过中点是不得已为之,走一圈是最长路径。 那么摘苹果就分成了三种情况,顺时针不过m采摘,逆时针不过m采摘,跨m采摘(至多一次)。预处理出单侧不跨m采摘的花费。 ldp记录采摘起点到顺时针的第i个苹果所需要的花费,那么 ldp[i]=ldp[i-K]+lcost[i]。 rdp记录采摘起点到逆时针的第i个苹果所需要的花费,那么 rdp[i]=rdp[i-K]+rcost[i]。 我们再枚举,跨越m的那次采摘的采摘区间,那么显然我们要让这次采摘覆盖单侧采摘中花费最大的那些苹果,即离起点最远的那些苹果。 假设这次采摘,在左侧摘i个,那么右侧摘K-i个, total_cost就由(ldp[lmax]+rdp[rmax])*2变成了(ldp[lmax-i]+rdp[rmax-(K-i)])*2+L。枚举过程中取最小值即可。

    //#include<bits/stdc++.h> #pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<queue> #include<vector> #include<algorithm> #define LS (root<<1) #define RS ((root<<1)|1) #define LSON LS,l,mid #define RSON RS,(mid+1),r #define MID mid=((l+r)/2) #define LL long long #define mm(a,b) memset(a,b,sizeof(a)) using namespace std; const int maxn=3e4+5; const LL Inf=1e18; vector<LL> ldp, rdp; int main(){ int T, n; int L, K; int a, b; scanf("%d",&T); while(T--){ ldp.clear(); rdp.clear(); ldp.push_back(0); rdp.push_back(0); scanf("%d%d%d",&L, &n, &K); for(int i=0;i<n;i++){ scanf("%d%d",&a, &b); while(b--){ if(2*a<L) ldp.push_back(a); else rdp.push_back(L-a); } } sort(ldp.begin(),ldp.end()); sort(rdp.begin(),rdp.end()); for(int i=K;i<ldp.size();i++) ldp[i]+=ldp[i-K];//把摘到i-K为止的cost累加到i上过 for(int i=K;i<rdp.size();i++) rdp[i]+=rdp[i-K]; LL ans=(ldp[(int)ldp.size()-1]+rdp[(int)rdp.size()-1])*2; for(int i=0;i<=K;i++){ a=max(0,(int)ldp.size()-1-i); b=max(0,(int)rdp.size()-1-(K-i)); LL tmp=(ldp[a]+rdp[b])*2; ans=min(ans,L+tmp); } printf("%lld\n",ans); } return 0; }
    转载请注明原文地址: https://ju.6miu.com/read-22218.html

    最新回复(0)