zoukankan      html  css  js  c++  java
  • [Luogu] CF229D Towers

    (Link)

    Description

    (n(1le{n}le5000))座塔排在一条直线上,从左到右每个塔的高度分别为(h_i(1le{h_i}le100000))

    每次操作你可以选择一座塔(假设是第(i)座),用吊车把它吊起来,然后放到与它相邻的一座塔上(可以是第(i-1)座也可以是第(i+1)座),这样,新塔的高度为两座塔的和,完成操作后,塔的总数减少一座。

    问最少需要多少次操作可以使得所有的塔从左到右形成一个非递减序列。

    Solution

    感觉和划分的64pts部分有点像?

    我们设(dp[i])表示以(i)为结尾的答案(最少操作次数),(ml[i])表示(i)所属的塔可能的最小高度。设(s_i)(h_i)的前缀和,那么我们枚举(jsim{i})被合并,如果(ml[j-1]le{s[i]-s[j-1]})就可以相应的更新即可。

    Code

    #include <bits/stdc++.h>
    
    using namespace std;
    
    int n, h[5005], dp[5005], s[5005], ml[5005];
    
    int read()
    {
    	int x = 0, fl = 1; char ch = getchar();
    	while (ch < '0' || ch > '9') { if (ch == '-') fl = -1; ch = getchar();}
    	while (ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3) + ch - '0'; ch = getchar();}
    	return x * fl;
    }
    
    int main()
    {
    	n = read();
    	for (int i = 1; i <= n; i ++ )
    	{
    		h[i] = read();
    		s[i] = s[i - 1] + h[i];
    	}
    	memset(dp, 0x3f, sizeof(dp));
    	memset(ml, 0x3f, sizeof(ml));
    	dp[0] = ml[0] = 0; 
    	for (int i = 1; i <= n; i ++ )
    	{
    		for (int j = 1; j <= i; j ++ )
    		{
    			if (ml[j - 1] <= s[i] - s[j - 1])
    			{
    				ml[i] = min(ml[i], s[i] - s[j - 1]);
    				dp[i] = min(dp[i], dp[j - 1] + i - j);
    			}
    		}
    	}
    	printf("%d
    ", dp[n]);
    	return 0;
    }
    
  • 相关阅读:
    数据结构前言
    Linux---远程连接、命令行基础、文件及目录管理
    HTTP协议
    Docker---dockerfile
    Docker---指令
    Docker---介绍
    进程模块的使用
    numpy---(精简)
    OpenJudge/Poj 2105 IP Address
    OpenJudge 2786 Pell数列
  • 原文地址:https://www.cnblogs.com/andysj/p/14015873.html
Copyright © 2011-2022 走看看