返回顶部

Vjudge Making the Grade

Making the Grade Vjudge

  • 题目描述:A straight dirt road connects two fields on FJ's farm, but it changes elevation more than FJ would like. His cows do not mind climbing up or down a single slope, but they are not fond of an alternating succession of hills and valleys. FJ would like to add and remove dirt from the road so that it becomes one monotonic slope (either sloping up or down).
    You are given N integers A1, ... , AN (1 ≤ N ≤ 2,000) describing the elevation (0 ≤ Ai ≤ 1,000,000,000) at each of N equally-spaced positions along the road, starting at the first field and ending at the other. FJ would like to adjust these elevations to a new sequence B1, . ... , BN that is either nonincreasing or nondecreasing. Since it costs the same amount of money to add or remove dirt at any position along the road, the total cost of modifying the road is
    |A1 - B1| + |A2 - B2| + ... + |AN - BN |
    Please compute the minimum cost of grading his road so it becomes a continuous slope. FJ happily informs you that signed 32-bit integers can certainly be used to compute the answer.
  • Input
  • Line 1: A single integer: N
  • Lines 2..N+1: Line i+1 contains a single integer elevation: Ai
  • Output
  • Line 1: A single integer that is the minimum cost for FJ to grade his dirt road so it becomes nonincreasing or nondecreasing in elevation.
  • Sample
    Input					Output
    7						3
    1
    3
    2
    4
    5
    3
    9
    
  1. 这题与 LCIS (线性DP,滚动数组)优化差不多
    可以LCIS回顾一下基本写法 这种复杂度为O(n^3)

    最长公共上升子序列
     for(int i=1;i<=n;i++)
     {
     	for(int j=1;j<=m;j++)
     	{
     		if(a[i]==b[j])
     		{
     			for(int k=0;k<j;k++) // 去找最长的子状态
     			{
     				if(b[k]<b[j]) f[i][j]=max(f[i][j],f[i-1][k]+1);
     			}
     			ans=max(ans,f[i][j]);
     		}
     		else f[i][j]=f[i-1][j];
     	}
     }
    

    经过优化,可优化为O(n^2)

    点击查看代码
    	for(int i=1;i<=n;i++)
    	{
    		int val=0; // val表示当前最大子状态
    		for(int j=1;j<=m;j++)
    		{
    			if(a[i]==b[j]) f[i][j]=val+1;
    			else f[i][j]=f[i-1][j];
    			// j即将增大为j+1,检查j能否更新val
    			if(b[j]<a[i]) val=max(val,f[i-1][j]);
    			ans=max(ans,f[i][j]);
    		}
    	}
    

    还可用滚动数组

    点击查看代码
    
    	for(int i=1;i<=n;i++)
    	{
    		int val=0; // val表示当前最大子状态
    		for(int j=1;j<=m;j++)
    		{
    			if(a[i]==b[j]) dp[j]=val+1;
    			// j即将增大为j+1,检查j能否更新val
    			if(b[j]<a[i]) val=max(val,dp[j]);
    			ans=max(ans,dp[j]);
    		}
    	}
    
    

    这题,其实就是把最大改为最小值

    LCIS

  • 这题也用到了类似离散思想题目-分级

    这篇文章讲到

  • 做这题,我们需要先证明只要存在某个 B 的值不在原序列A中,我们一定可以将它调整成原序列中的值,且结果不会变差。

    image
    存在一种B序列符合题意并且B中数都是A中出现过的
    如图中间相差部分,可以调整蓝线B中值使|B-A|最小,这时B可能为左面A凸点,也可能为
    B右凸点(看情况)

    正解
    #include <bits/stdc++.h>
    using namespace std;
    
    const int N=2005;
    int a[N],b[N],f[N][N];
    int solve(int n)
    {
    	for(int i=1;i<=n;i++)
    	{
    		int val=1e9;
    		for(int j=1;j<=n;j++)
    		{
    			val=min(val,f[i-1][j]);
    			f[i][j]=val+abs(a[i]-b[j]);
    		}
    	}
    	int res=1e9;
    	for(int i=1;i<=n;i++) res=min(res,f[n][i]);
    	return res;
    }
    signed main()
    {
    	ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    	int n;
    	cin>>n;
    	for(int i=1;i<=n;i++) cin>>a[i], b[i]=a[i];
    	sort(b+1,b+1+n);
    	int ans=solve(n);
    	reverse(a+1,a+1+n);
    	ans=min(ans,solve(n));
    	cout<<ans<<endl;
    	return 0;
    }
    
    
posted @ 2024-02-19 07:45  wlesq  阅读(9)  评论(0编辑  收藏  举报