• BZOJ-1587|前缀和 预处理 dp||叶子合并leaves


    叶子合并leaves

    Description

    在一个美丽的秋天,丽丽每天都经过的花园小巷落满了树叶,她决定把树叶堆成K堆,小巷是笔直的 共有N片树叶(树叶排列也是笔直的),每片树叶都有一个重量值,并且每两片想邻的树叶之间的距离都是1 现把所有的树叶按从左到右的顺序进行编号,编号为1..N。丽丽移动每片树叶所消耗能量等于这片树叶的重量 乘以移动的距离,丽丽决定分K天完成,每天堆一堆,并且规定只能把树叶往左移动,因为丽丽每天都是从右往左 经过小巷的。求丽丽完成任务所消耗的最少能量。

    Input

    输入的第一行为两个用空格隔开的正整数N和K。后面有N行 每行一个正整数表示叶子的重量(第i+1行表示第i片树叶的重量)

    Output

    输出为一个整数,表示把树叶堆成K堆所消耗的最少体力。

    Sample Input 1

    5 2
    1
    2
    3
    4
    5

    Sample Output 1

    13

    Hint

    N在(0,1001)

    K在(0,11)

    每片树叶的重量(0,1001)

    思路:

    前缀和: pre[i] 前i个叶子的重量和
    预处理:sum[i][j] 前i个叶子移动到第j个位置的总花费
    dp递推: dp[i][j] 前i个叶子分成k堆的最小值 == min(前j个分成一堆 + j~i个分成的一堆 共k(k~K)堆)的最小值i和j

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    
    /*
    前缀和: pre[i] 前i个叶子的重量和 
    预处理:sum[i][j] 前i个叶子移动到第j个位置的总花费
    dp递推: dp[i][j] 前i个叶子分成k堆的最小值  == min(前j个分成一堆 + j~i个分成的一堆 共k(k~K)堆)的最小值i和j
    */ 
    
    const int maxn = 1010;
    int n,K;
    int a[maxn];
    int pre[maxn];
    int sum[maxn][maxn];
    int dp[maxn][maxn];
    
    int main(){
    	scanf("%d%d",&n,&K);
    	for(int i=n;i>=1;i--){ //从右往左输入以便后面正序遍历
    		scanf("%d",&a[i]);
    	}
    	pre[0] = 0;
    	for(int i=1;i<=n;i++){
    		pre[i] = pre[i-1] + a[i];//前缀和 
    	}
    	//预处理sum[i][j] 
    	for(int i=1;i<=n;i++){
    		for(int j=i;j<=n;j++){
    			if(i==j) sum[i][j] = sum[i-1][j-1] + pre[i-1];//当i == j,等于 前i-1个叶子(加上第i个叶子也一样 但是j>i的 所以分类讨论递推式)移动到j-1个位置的消耗 + 前i-1个叶子一起移动到第j个位置(前缀和pre[i-1]) 
    			else sum[i][j] = sum[i][j-1] + pre[i];//等于 前i-1个叶子移动到j-1个位置的消耗 + 前i个叶子一起移动到第j个位置(前缀和pre[i])
    		}
    	}
    	//初始化dp 
    	memset(dp,0x3f3f3f3f,sizeof(dp));
    	for(int i=1;i<=n;i++) dp[i][1] = sum[i][i]; //只能分成j==1堆时,dp[i][j]等于把前i堆移动到最后的i个叶子上(sum[i][i])
    	
    	for(int k=2;k<=K;k++){//分成k堆 
    		for(int i=1;i<=n;i++){//前i个,到n 
    			for(int j=1;j<i;j++){//j堆,最多到i堆
    				dp[i][k] = min(dp[i][k],dp[j][k-1] + sum[i][i] - sum[j][i]);//状态转移方程: 前i个分成k堆 等于 min(前j个分成k-1堆 加上 第j+1~第i个分成另外一堆)的最小花费 
    			}
    		}
    	}
    	printf("%d
    ",dp[n][K]);
    	return 0;
    } 
    
  • 相关阅读:
    Mac挂载分区
    连接SFTP命令
    【转】10.13.6蓝牙失效的解决方法(Broadcom-BCM94352z-DW1560)
    Jetbrains2020系列配置路径变动(Pycharm2020双击无法打开)
    libtorch 常用api函数示例(史上最全、最详细)
    有用链接
    cuda 编程1
    CMakeLists.txt
    模型压缩--剪枝,tensorrt实验调研
    iou map TP TN FP FN Precision Recall
  • 原文地址:https://www.cnblogs.com/fisherss/p/10739078.html
Copyright © 2020-2023  润新知