zoukankan      html  css  js  c++  java
  • CF559E Gerald and Path

    cf

    两回啊两回...

    不妨先将所有线段按照端点从小到大排序,并假设只能往右放,然后强行套上一个dp(f_{i,j})表示放完前(i)个线段,最右覆盖到(j)的答案,转移时枚举下一条放进来的线段,因为现在是只往右放,所以只能去覆盖(j)以后的部分,转移(f_{i,j}+min(a_k+l_k-j,l_k) o f_{k,max(a_k+l_k,j)})

    然后这题里面现在是可以往左放的.如果当前线段往右放,那么因为放过的线段都在它的前面,所以它覆盖的一定是当前的最右端(j)以后的位置.但是如果往左放,可能会出现覆盖的新段有多个段的问题.为了避免这种情况,因为前面我们是枚举在(i)后面的一个线段(k),那么先不考虑(i,k)之间的线段,只考虑(k)覆盖左边以及前面覆盖最右端(j)的影响,这里贡献为(min(a_k-j,l_k)).然后对于(i,k)之间的线段,我们将他们全部向右放,并考虑贡献,如果这一些线段最右端为(mx),那么这里贡献为(mx-a_k)

    至于为什么这样子是对的,首先可以发现这样子转移贡献一定不会算多,因为每次覆盖的地方都是之前没覆盖过的地方;然后注意到(k)往左放的时候,可能到达的最左端点比当前(i)的左端点还要左,但并没有考虑(i)左端点以左的部分,那如果出现这种情况,其实(i)左端点以左的贡献可以在(i)前面的位置(i')被统计,而在(i')(i)也就是有一个往右贡献;至于在(i')处转移时(i)往左更优怎么办,那就会先统计(i)往左的贡献,然后在(i)处转移是统计(k)的贡献,因为(i)往左更优,说明(k)往左不会盖到(i)线段左端点

    形式化的,下面的状态为(f_{i,j,k(0/1)})表示前(i)个线段,覆盖到最右端的线段为(j),方向朝左/朝右,这样我们可以把某条线段(x)的右端点表示为(a_x+k*l_x).然后转移的时候记录枚举过的线段的最右的(j,k),记为(nj,nk),然后当前枚举线段(x)方向(p),转移可以写成

    (f_{i,j,k}+min((a_{x}+p*l_{x})-(a_{j}+k*l_{j}),l_x)+(a_{nj}+nk*l_{nj})-(a_{x}+p*l_{x}) o f_{x,nj,nk})

    #include<bits/stdc++.h>
    #define LL long long
    #define db double
    
    using namespace std;
    const int N=100+10,M=205,mod=1e9+7;
    int rd()
    {
        int x=0,w=1;char ch=0;
        while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+(ch^48);ch=getchar();}
        return x*w;
    }
    struct node
    {
    	int x,y;
    	bool operator < (const node &bb) const {return x<bb.x;}
    }a[N];
    int n,f[N][N][2];
    int ps(int x,int y){return a[x].x+a[x].y*y;}
    
    int main()
    {
    	n=rd();
    	for(int i=1;i<=n;++i) a[i].x=rd(),a[i].y=rd();
    	a[++n]=(node){-(int)2e8,0};
    	sort(a+1,a+n+1);
    	memset(f,-0x3f3f3f,sizeof(f));
    	f[1][1][0]=0;
    	int ans=0;
    	for(int i=1;i<=n;++i)
    		for(int j=1;j<=i;++j)
    			for(int k=0;k<=1;++k)
    			{
    				ans=max(ans,f[i][j][k]);
    				int nj=j,nk=k;
    				for(int l=i+1;l<=n;++l)
    					for(int p=0;p<=1;++p)
    					{
    						if(ps(nj,nk)<=ps(l,p)) nj=l,nk=p;
    						f[l][nj][nk]=max(f[l][nj][nk],f[i][j][k]+min(ps(l,p)-ps(j,k),a[l].y)+ps(nj,nk)-ps(l,p));
    					}
    			}
    	printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    The Ubuntu version detected is too old (< 10.04). Please refer to VMware KB article 2147454 to learn how to obtain and install VMware Tools on this system
    Metasploit渗透测试指南:修订版 勘误
    栈溢出基础
    修改peda颜色
    linux 修改文件夹颜色 终端颜色
    fadetop bing wallpaper
    odoo 去除动作菜单的删除按钮
    crontab详解
    odoo 创建初始数据库 切换当前数据库
    24 单链表的遍历与优化
  • 原文地址:https://www.cnblogs.com/smyjr/p/12288586.html
Copyright © 2011-2022 走看看