• Telephone Wire G


    题目描述

    Farmer John's cows are getting restless about their poor telephone service; they want FJ to replace the old telephone wire with new, more efficient wire. The new wiring will utilize $N (2 ≤ N ≤ 100,000) $already-installed telephone poles, each with some heighti meters \((1 ≤ height_i ≤ 100)\). The new wire will connect the tops of each pair of adjacent poles and will incur a penalty cost\(C_×\) the two poles' height difference for each section of wire where the poles are of different heights \((1 ≤ C ≤ 100)\). The poles, of course, are in a certain sequence and can not be moved.

    Farmer John figures that if he makes some poles taller he can reduce his penalties, though with some other additional cost. He can add an integer X number of meters to a pole at a cost of \(X_2\).

    Help Farmer John determine the cheapest combination of growing pole heights and connecting wire so that the cows can get their new and improved service.

    输入格式

    * Line 1: Two space-separated integers: N and C

    * Lines \(2..N+1\): Line i+1 contains a single integer: \(height_i\)

    输出格式

    * Line 1: The minimum total amount of money that it will cost Farmer John to attach the new telephone wire.

    样例 #1

    样例输入 #1

    5 2
    2
    3
    5
    1
    4
    

    样例输出 #1

    15
    

    首先打出暴力dp,记录\(dp_{i,j}\)为前面\(i\)棵树且第\(i\)棵树的高度为\(j\)的最小代价。
    \(dp_{i,k}=min(\forall h_i\le j\le 100,dp_{i-1,j}+(k-h[i])^2+|k-j|*c)\)

    #include<bits/stdc++.h>
    using namespace std;
    const int N=100005;
    int n,c,h[N],dp[N][105],ans=2e9;
    int main()
    {
    	memset(dp,0x3f,sizeof(dp));
    	scanf("%d%d",&n,&c);
    	for(int i=1;i<=n;i++)
    		scanf("%d",h+i);
    	for(int i=h[1];i<=100;i++)
    		dp[1][i]=(i-h[1])*(i-h[1]);
    	for(int i=2;i<=n;i++)
    		for(int k=h[i];k<=100;k++)
    			for(int j=0;j<=100;j++)			
    				dp[i][k]=min(dp[i][k],dp[i-1][j]+(k-h[i])*(k-h[i])+abs(k-j)*c);
    	for(int i=0;i<=100;i++)
    		ans=min(ans,dp[n][i]);
    	printf("%d",ans);
    	return 0;
    }
    

    复杂度明显不过关,但是开个O2可以通过洛谷数据

    开始考虑正解,在式子中,\((k-h_i)^2\)可以提到外面,同时可以把绝对值的两种情况分开考虑,要考虑的式子就是
    \(dp_{i-1,j}+k*c-j*c(k\ge j)\)
    \(dp_{i-1,j}+j*c-k*c(k<j)\)
    k*c也可以提到外面,然后对\(dp_{i-1,j}-j*c\)维护前缀最大值,对\(dp_{i-1,j}+j*c\)维护后缀最大值,就可以实现O(1)转移,可以通过此题。

    #include<bits/stdc++.h>
    using namespace std;
    const int N=100005;
    int n,c,h[N],dp[N][105],ans=2e9,s[N][105],t[N][105];
    int main()
    {
    	memset(dp,0x3f,sizeof(dp));
    	scanf("%d%d",&n,&c);
    	for(int i=1;i<=n;i++)
    		scanf("%d",h+i);
    	for(int i=h[1];i<=100;i++)
    		dp[1][i]=(i-h[1])*(i-h[1]);
    	s[1][0]=dp[1][0],t[1][100]=dp[1][100]+100*c;
    	for(int j=1;j<=100;j++)
    		s[1][j]=min(s[1][j-1],dp[1][j]-j*c);
    	for(int j=99;j>=0;j--)
    		t[1][j]=min(t[1][j+1],dp[1][j]+j*c);
    	for(int i=2;i<=n;i++)
    	{
    		for(int k=h[i];k<=100;k++)
    			dp[i][k]=min(s[i-1][k]+k*c,t[i-1][k]-k*c)+(k-h[i])*(k-h[i]);
    		s[i][0]=dp[i][0],t[i][100]=dp[i][100]+100*c;
    		for(int j=1;j<=100;j++)
    			s[i][j]=min(s[i][j-1],dp[i][j]-j*c);
    		for(int j=99;j>=0;j--)
    			t[i][j]=min(t[i][j+1],dp[i][j]+j*c);
    	}
    	for(int i=0;i<=100;i++)
    		ans=min(ans,dp[n][i]);
    	printf("%d",ans);
    	return 0;
    }
    
  • 相关阅读:
    HDU 1385 Minimum Transport Cost
    TOJ 3488 Game Dice
    TOJ 1717 WOJ
    POJ 2553 The Bottom of a Graph
    TOJ 1836 Play on Words
    利用OpenCV建立视差图像
    分享一个PyTorch医学图像分割开源库
    WACV 2021 论文大盘点-图像分割篇
    SolidWorks动画教程(1):简单动画制作
    VS2013安装及破解教程
  • 原文地址:https://www.cnblogs.com/mekoszc/p/16328217.html
Copyright © 2020-2023  润新知