• 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;
    }
    
  • 相关阅读:
    Charles 弱网测试
    jmespath 教程
    Fiddler查看接口响应时间
    Fiddler如何模拟弱网环境进行测试
    Github 上配置 Personal Token Key
    fiddler抓取app请求
    Charles 设置https 抓包
    PostgreSQL触发器使用实践——数据审计(转载)
    使用aop注解实现表单防重复提交功能(转载)
    转载( Spring Cloud gateway 网关拦截Post请求日志)
  • 原文地址:https://www.cnblogs.com/mekoszc/p/16328217.html
Copyright © 2020-2023  润新知