1 条题解

  • 6
    @ 2023-11-5 20:24:52
    思路 $\\$这道题的数据范围不需要最值优化 $\\$首先第一步当然是把这些点按照坐标从小到大排序啦。 $\\$由贝西 只朝一个方向跳跃,所以要分两种情况:一种是一直向右跳,一种是一直向左跳。 当一直向右跳时,定义f[i][j]表示当前贝西已经跳到了第$i$个点,且上一步是从第$j$个点跳到第$i$个点的最大总得分。那么 $\\$f[i][j]=max{f[j][k]+s[i]} 其中$k<=j<i,x(j)−x(k)≤x(i)−x(j)。$ $\\$考虑边界$f[i][i]=s[i]$。(即一开始站在任意一个点上) $\\$当一直向左跳时也同理,只不过方向倒过来而已。只要做两次 DP 就可以了。 $\\$这个时候时间复杂度为 $O(N^3)$。
    代码
    
    #include <bits/stdc++.h>
    using namespace std;
    const int N=105;
    int n,f[N][N],ans;
    struct Point{
    	int x,s;
    } point[N];
    bool cmp(Point a,Point b)
    {
    	return a.x<b.x;
    }
    int main()
    {
    	cin>>n;
    	for(int i=1;i<=n;i++) 
    		cin>>point[i].x>>point[i].s;
    	sort(point+1,point+1+n,cmp);
    	for(int i=1;i<=n;i++)
    	{
    		f[i][i]=point[i].s;
    		for(int j=1;j<i;j++)
    		{
    			int k=j;
    			while(((point[i].x-point[j].x)>=(point[j].x-point[k].x))&&k>0)
    			{
    				f[i][j]=max(f[i][j],f[j][k]+point[i].s);
    				k--;
    			}
    			ans=max(ans,f[i][j]);
    		}
    	}
    	for(int i=n;i>=1;i--)
    	{
    		//f[i][i]=point[i].s;
    		for(int j=n;j>i;j--)
    		{
    			int k=j;
    			while(((point[j].x-point[i].x)>=(point[k].x-point[j].x))&&k<=n)
    			{
    				f[i][j]=max(f[i][j],f[j][k]+point[i].s);
    				k++;
    			}
    			ans=max(ans,f[i][j]);
    		}
    	}
    	cout<<ans;
    }
    
    
    • 1

    信息

    ID
    552
    时间
    1000ms
    内存
    256MiB
    难度
    1
    标签
    (无)
    递交数
    152
    已通过
    103
    上传者