【Codeforces559E】Gerald and Path

来源:互联网 发布:mysql官网下载 编辑:程序博客网 时间:2024/06/16 09:01

题意:

  • 一条路上有n盏不同的灯,每盏灯所在位置为pi,向左或者向右可以照射的距离为li,求最大总照射长度。
  • n100,li,pi108

题解:

  • 这道题dp思路似乎都很神奇?
  • dp[i][j][k]表示到第i盏灯(按位置从左到右),最左边的需要覆盖到的位置j(0代表不存在未覆盖),最右端位置是k,包括了这段实际没有覆盖的最大总长度。
  • 考虑转移:
    • 向右照射,且之前的最左边需要覆盖的位置不变,转移方程:
      • dp[i][j][max(R[i],k)]=max(dp[i][j][max(R[i],k)],dp[i1][j][k]+max(0,R[i]k]))
    • 向左照射,且覆盖掉了原来实际没有覆盖(或者原来没有未覆盖)的部分,转移方程:
      • dp[i][0][max(p[i],k)]=max(dp[i][0][max(p[i],k)],dp[i1][j][k]+max(0,p[i]k]))(L[i]j)
    • 向右照射,且原来没有未覆盖部分,最右边位置在当前灯位置左边,取最右边位置后某一处j到当前位置作为假装覆盖实际没有覆盖部分(或者不选取),转移方程:
      • dp[i][k][R[i]]=max(dp[i][k][R[i]],dp[i1][0][j]+R[i]k)(jk<p[i])
    • 向左照射,且原来没有未覆盖部分,最右边位置在当前灯照射左边界左边,取最右边位置后某一处j到当前位置作为假装覆盖实际没有覆盖部分(或者不选取),转移方程:
      • dp[i][k][max(x[i],j)]=max(dp[i][k][max(x[i],j)],dp[i1][0][j]+p[i]k)(jk<L[i])
  • 总时间复杂度O(n3)

代码:

#include <bits/stdc++.h>#define gc getchar()#define N 109using namespace std;int n,x[N],l[N],num[N],L[N],R[N],a[N],b[N],dp[N][N*3][N*3],ans;vector <int> lsh;int read(){    int x=1;    char ch;    while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;    int s=ch-'0';    while (ch=gc,ch>='0'&&ch<='9') s=s*10+ch-48;    return s*x;}bool cmp(int aa,int bb){    return x[aa]<x[bb];}int main(){    n=read();    for (int i=1;i<=n;i++)    {        x[i]=read(),l[i]=read(),num[i]=i;        lsh.push_back(x[i]-l[i]),lsh.push_back(x[i]),lsh.push_back(x[i]+l[i]);    }    sort(num+1,num+n+1,cmp);    sort(lsh.begin(),lsh.end());    lsh.erase(unique(lsh.begin(),lsh.end()),lsh.end());    for (int i=1;i<=n;i++)        a[i]=x[num[i]],b[i]=l[num[i]];    for (int i=1;i<=n;i++)    {        L[i]=lower_bound(lsh.begin(),lsh.end(),a[i]-b[i])-lsh.begin()+1;        x[i]=lower_bound(lsh.begin(),lsh.end(),a[i])-lsh.begin()+1;        R[i]=lower_bound(lsh.begin(),lsh.end(),a[i]+b[i])-lsh.begin()+1;    }    for (int i=1;i<=n;i++)    {        for (int j=1;j<=lsh.size();j++)            for (int k=j;k<=lsh.size();k++)            {                dp[i][j][max(R[i],k)]=max(dp[i][j][max(R[i],k)],dp[i-1][j][k]+max(0,lsh[R[i]-1]-lsh[k-1]));                if (L[i]<=j) dp[i][0][max(x[i],k)]=max(dp[i][0][max(x[i],k)],dp[i-1][j][k]+max(0,lsh[x[i]-1]-lsh[k-1]));            }        for (int j=1;j<=lsh.size();j++)        {            if (j<x[i])            {                dp[i][0][R[i]]=max(dp[i][0][R[i]],dp[i-1][0][j]+lsh[R[i]-1]-lsh[x[i]-1]);                for (int k=j;k<x[i];k++)                    dp[i][k][R[i]]=max(dp[i][k][R[i]],dp[i-1][0][j]+lsh[R[i]-1]-lsh[k-1]);            }            else                dp[i][0][max(R[i],j)]=max(dp[i][0][max(R[i],j)],dp[i-1][0][j]+max(0,lsh[R[i]-1]-lsh[j-1]));            dp[i][0][max(x[i],j)]=max(dp[i][0][max(x[i],j)],dp[i-1][0][j]+max(0,lsh[x[i]-1]-lsh[max(j,L[i])-1]));            for (int k=j;k<L[i];k++)                dp[i][k][max(x[i],j)]=max(dp[i][k][max(x[i],j)],dp[i-1][0][j]+lsh[x[i]-1]-lsh[k-1]);        }    }    for (int i=1;i<=lsh.size();i++)        ans=max(ans,dp[n][0][i]);    printf("%d\n",ans);    return 0;}
原创粉丝点击