• CF559E Gerald and Path(DP)


    CF559E Gerald and Path

    \(dp(i,p)\) 表示完成前 \(i\) 条线段的覆盖,最右端位于 \(p\) 点的最大收益。

    转移?向下一条线段转移时加上他们中间的距离?发现这样没有办法统计 \(p\) 点以前的空位了!

    \(\color{yellow}{\bigstar\texttt{Trick}}\):如果出现上面没有办法统计 \(p\) 点以前的空位的情况,说明覆盖 \(p\) 点的这条线段是没有用的,每次只需要考虑有用的线段

    若要枚举有用的线段,从 \(i\) 点枚举下一个有用的线段 \(k\),钦定 \([i+1,k-1]\) 之间的线段都是没有用的,这样就可以像上面一样转移了。

    但是,如果没有用的线段中出现一个线段它的右端点超过了 \(k\) 线段的右端点呢?那就再扫过 \([i+1,k-1]\) 线段的时候统计下最右边端,再加上它与 \(k\) 线段右端的贡献即可。

    实现的时候记 \(p\) 点只用记录最右端线段编号和朝向即可,设 \(dp(i,j,p)\) 表示到 \(i\) 线段为止,最右边的线段是 \(j\),它的朝向为 \(p\) 的最大收益。

    \[dp(k,x,y)\leftarrow dp(i,j,p)+\min(r_k-p,len_k)+r_x-r_k \]

    #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;
    }
    
  • 相关阅读:
    在 Mac 上使用 PICT 进行 Pairwise 测试
    组合测试术语:Pairwise/All-Pairs、OATS(Orthogonal Array Testing Strategy)
    小白懂算法之二分查找
    小白也能看懂的JVM内存区域
    小白也能看懂的JDK1.8前_HashMap的扩容机制原理
    小白也能看懂的ArrayList的扩容机制
    activenq整合spring之队列消费者
    activemq整合spring之队列生产者
    ActiveMQ之Broker
    ActiveMQ_JMS签收
  • 原文地址:https://www.cnblogs.com/EricQian/p/16585902.html
Copyright © 2020-2023  润新知