1. 程式人生 > >[Codeforces 28D] Do not fear,DravDe is kind

[Codeforces 28D] Do not fear,DravDe is kind

cmp char cto clu else push 決策單調 ID turn

Brief Intro:

對於四元組(v,c,l,r),求其子序列中v最大的和,並使其滿足:

1、Ci+Li+Ri相同

2、L1=0,Rn=0

3、Li=Sigma(C1...Ci-1)

Solution:

算是有條件約束的DP吧

設dp[k]為選到k且選k的最大值

對於每個條件,我們這樣處理:

1、將所有數據按Ci+Li+Ri的和進行分組處理

2、當Li=0時,將其視為起點;當Ri=0時,用dp[i]去更新res

3、此條件可轉換為:僅當Lp=Lq+Cq時,dp[p]可由dp[q]轉移而來

於是我們將數組按SUM排序後,用Best_val[t]記錄Lk+Ck=t時最大的dp[k],用Best_id[t]記錄Lk+Ck=t時最大的k,這樣每次dp[k]由Best_val[Lk]更新,再由Best_id[Lk]更新父親節點即可

#include <bits/stdc++.h>

using namespace std;

inline int read()
{
    char ch;int num,f=0;
    while(!isdigit(ch=getchar())) f|=(ch==-);
    num=ch-0;
    while(isdigit(ch=getchar())) num=num*10+ch-0;
    return f?-num:num;
}

template<class T> inline void putnum(T x)
{
    if(x<0
)putchar(-),x=-x; register short a[20]={},sz=0; while(x)a[sz++]=x%10,x/=10; if(sz==0)putchar(0); for(int i=sz-1;i>=0;i--)putchar(0+a[i]); putchar( ); } const int MAXN=1e5+10; int n; struct truck { int v,c,l,r,num; }dat[MAXN]; int pre[MAXN],dp[MAXN],b_val[MAXN],b_id[MAXN],T[MAXN],start=-1
,res=0; bool cmp(truck x,truck y) { if(x.c+x.l+x.r==y.c+y.l+y.r) return x.num<y.num; return x.c+x.l+x.r<y.c+y.l+y.r; } int main() { n=read(); for(int i=1;i<=n;i++) dat[i].v=read(),dat[i].c=read(),dat[i].l=read(),dat[i].r=read(),dat[i].num=i; sort(dat+1,dat+n+1,cmp); for(int i=1,j=1;i<=n;i=j) { while(j<=n && dat[i].c+dat[i].l+dat[i].r==dat[j].c+dat[j].l+dat[j].r) j++; for(int k=i;k<j;k++) { if(!dat[k].l) dp[k]=dat[k].v,pre[k]=-1; else if(T[dat[k].l]==i) { dp[k]=b_val[dat[k].l]+dat[k].v; pre[k]=b_id[dat[k].l]; } int t=dat[k].l+dat[k].c; if(T[t]!=i || dp[k]>b_val[t]) { b_val[t]=dp[k];T[t]=i;b_id[t]=k; } if(!dat[k].r && dp[k]>res) res=dp[k],start=k; } } vector<int> res; while(start!=-1) res.push_back(dat[start].num),start=pre[start]; putnum(res.size());puts(""); if(!res.size()) return 0; for(int i=res.size()-1;i>=0;i--) putnum(res[i]); return 0; }

Review:

1、 註意子序列是不能改變相對次序的,因此排序時在SUM相同時要按原ID作為關鍵字排序(保證穩定性)

2、 對vector.size()少進行減法運算,防止unsigned int溢出

3、 對於具有決策單調性的DP,只要記錄當前轉移態前最優的狀態即可

[Codeforces 28D] Do not fear,DravDe is kind