CF559E Gerald and Path(DP)
设 表示完成前 条线段的覆盖,最右端位于 点的最大收益。
转移?向下一条线段转移时加上他们中间的距离?发现这样没有办法统计 点以前的空位了!
:如果出现上面没有办法统计 点以前的空位的情况,说明覆盖 点的这条线段是没有用的,每次只需要考虑有用的线段。
若要枚举有用的线段,从 点枚举下一个有用的线段 ,钦定 之间的线段都是没有用的,这样就可以像上面一样转移了。
但是,如果没有用的线段中出现一个线段它的右端点超过了 线段的右端点呢?那就再扫过 线段的时候统计下最右边端,再加上它与 线段右端的贡献即可。
实现的时候记 点只用记录最右端线段编号和朝向即可,设 表示到 线段为止,最右边的线段是 ,它的朝向为 的最大收益。
#define Maxn 105
int n,ans;
int dp[Maxn][Maxn][2];
struct Seg
{
int pos,len;
Seg(int Pos=0,int Len=0):pos(Pos),len(Len){}
inline bool friend operator < (Seg x,Seg y) { return x.pos<y.pos; }
}s[Maxn];
int main()
{
n=rd();
for(int i=1,p,l;i<=n;i++) p=rd(),l=rd(),s[i]=Seg(p,l);
sort(s+1,s+n+1),s[0].pos=-inf;
for(int i=0;i<=n;i++)
for(int j=0;j<=i;j++) for(int p=0;p<2;p++)
{
int rn=s[j].pos+p*s[j].len,maxx=-inf,pos=-1,d;
ans=max(ans,dp[i][j][p]);
for(int k=i+1;k<=n;k++) for(int q=0;q<2;q++)
{
int cur=s[k].pos+q*s[k].len;
if(cur>=maxx) maxx=cur,pos=k,d=q;
dp[k][pos][d]=max(dp[k][pos][d],
dp[i][j][p]+min(cur-rn,s[k].len)+maxx-cur);
}
}
printf("%d\n",ans);
return 0;
}
本文作者:EricQian's Blog
本文链接:https://www.cnblogs.com/EricQian/p/16585902.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
分类:
标签:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步