zoukankan      html  css  js  c++  java
  • P1281 书的复制 题解

    题目传送门

    暑期自己想出来的第 2 道 dp //qwq

    题目分析

    一看到题很容易想到二分答案,代码也比较简单,就不放了(其实是我没打

    因为算法标签写着是 dp 我才做这题的,那就讲讲 dp 的做法 (这题 dp 的复杂度好像比二分还高)

    目前还没有想出 O(mk) 的做法(以后也想不出),只有 O(m²k)

    f[i][j] 表示前 i 本书由 j 个人抄写的最少时间

    考虑第 j 个人,这个人的任务有 i 种情况:i、i-1—i、i-2—i......1—i

    所以就有了三重循环的算法,在枚举 i、j 里面在枚举 k(k为第 j 个人任务的起始点,最后一本是 i)

    转移方程也很简单,只有一句 

    	for (int i = 1; i <= m; i++)
    	  for (int j = 1; j <= k; j++) 
    	    for (int p = 1; p <= i; p++) 
    		  f[i][j] = min (f[i][j], max(f[p-1][j-1], s[i] - s[p-1])); 
    

    算出 f[m][k] 的最小值后统计方案就好做了

    直接用贪心,从后向前走一遍,记录每个人的任务区间

    代码

    代码也很短~~~

    #include <bits/stdc++.h>
    using namespace std;
    int m, k, a[538], s[538], f[538][538], w[538], tmp;
    int main() {
    	scanf ("%d %d", &m, &k);  tmp = k;  w[k+1] = m;
    	for (int i = 1; i <= m; i++)  scanf ("%d", a + i), s[i] = s[i-1] + a[i];
    	memset (f, 0x3f, sizeof(f));
    	for (int i = 0; i <= k; i++)  f[0][i] = 0;
    	for (int i = 1; i <= m; i++)
    	  for (int j = 1; j <= k; j++) 
    	    for (int p = 1; p <= i; p++) 
    		  f[i][j] = min (f[i][j], max(f[p-1][j-1], s[i] - s[p-1])); 
    	for (int j = m; j >= 1; j--) 
    	    if (s[w[tmp+1]] - s[j-1] > f[m][k])  w[tmp--] = j;   //记录每个人的任务端点 
    	for (int i = 1; i <= k; i++) printf ("%d %d
    ", w[i] + 1, w[i+1]);
    	return 0;
    }
    

      

  • 相关阅读:
    对Promise的理解?
    对JavaScript垃圾回收机制的理解?
    说明split()与join()函数的区别?
    目标检测评估标准
    训练自己的数据集
    ssd_mobilenet_demo
    c++读取数据
    0XFF
    python读取数据
    快速排序
  • 原文地址:https://www.cnblogs.com/whx666/p/11136583.html
Copyright © 2011-2022 走看看