码迷,mamicode.com
首页 > 其他好文 > 详细

codeforces #313 div1 E

时间:2016-04-12 12:34:28      阅读:134      评论:0      收藏:0      [点我收藏+]

标签:

首先我们要注意到一个事情

如果一个灯塔向左覆盖,那么比他小的某个灯塔如果向左覆盖的端点大于当前塔向左覆盖的端点,他一定向右覆盖

对于当前灯塔向右覆盖也是同理

那么我们只需要记录当前覆盖到的端点就可以完成转移了

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<vector>
using namespace std;

typedef long long LL;
const int maxn=310;
const LL oo=1LL<<62;
int n,m,a[maxn],b[maxn],p[maxn],L[maxn],R[maxn];
LL dp[maxn][maxn][maxn],ans;
vector<int>V;
void cmax(LL &a,LL b){if(a<b)a=b;}

int main(){
	scanf("%d",&n);
	for(int i=0;i<n;++i){
		scanf("%d%d",&a[i],&b[i]);
		V.push_back(a[i]);V.push_back(a[i]+b[i]);V.push_back(a[i]-b[i]);
	}
	sort(V.begin(),V.end());
	V.erase(unique(V.begin(),V.end()),V.end());
	for(int i=0;i<n;++i){
		p[i]=lower_bound(V.begin(),V.end(),a[i])-V.begin();
		L[i]=lower_bound(V.begin(),V.end(),a[i]-b[i])-V.begin();
		R[i]=lower_bound(V.begin(),V.end(),a[i]+b[i])-V.begin();
	}
	m=V.size();
	for(int i=0;i<m;++i){
		for(int j=0;j<m;++j){
			for(int k=0;k<m;++k){
				dp[i][j][k]=-oo;
			}
		}
	}
	for(int i=0;i<m;++i)dp[0][0][i]=0;
	for(int i=0;i<m-1;++i){
		int pos=-1;
		for(int j=0;j<n;++j)if(p[j]==i)pos=j;
		for(int j=0;j<m;++j){
			for(int k=0;k<m;++k){
				if(dp[i][j][k]>=0){
					if(pos==-1){
						cmax(dp[i+1][j][k],dp[i][j][k]+(j>=i+1||k<=i?(V[i+1]-V[i]):0));
					}else{
						cmax(dp[i+1][max(j,R[pos])][k],dp[i][j][k]+V[i+1]-V[i]);
						if(k==L[pos]){
							for(int l=k;l<m;++l)cmax(dp[i+1][max(j,i)][l],dp[i][j][k]+(j>=i+1||l<=i?(V[i+1]-V[i]):0));
						}
					}
				}
			}
		}
	}
	ans=0;
	for(int i=0;i<m;++i)cmax(ans,dp[m-1][i][m-1]);
	printf("%I64d\n",ans);
	return 0;
}

  

codeforces #313 div1 E

标签:

原文地址:http://www.cnblogs.com/joyouth/p/5381981.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!