递推DP UVA 473 Raucous Rockers

题目传送门

题意:n首个按照给定顺序存在m张光盘里,每首歌有播放时间ti,并且只能完整的存在一张光盘里,问最多能存几首歌

分析:类似01背包和完全背包,每首歌可存可不存,存到下一张光盘的情况是当前存不下了。dp[i][j][k] 表示前i首歌,存在前j张光盘,光盘已存k时间时最多能存多少歌曲。状态转移方程:dp[i][j] = max (dp[i-1][j][k], dp[i-1][j][k-a[i]] + 1, dp[i-1][j-1][t] + 1) (分别代表不存,还能存,下一张存的状态)

收获:状态转移明确,常见的DP题

代码:

/************************************************
* Author        :Running_Time
* Created Time  :2015-8-29 11:39:33
* File Name     :UVA_473.cpp
 ************************************************/

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <bitset>
#include <cstdlib>
#include <ctime>
using namespace std;

#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
typedef long long ll;
const int N = 1e3 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
int dp[900][120][120];
int a[N];

int main(void)    {
    int T;  scanf ("%d", &T);
    while (T--) {
        int n, m, t;    scanf ("%d%d%d", &n, &t, &m);
        int cnt = 0;
        for (int i=1; i<=n; ++i)    {
            int x;
            if (i == 1) scanf ("%d", &x);
            else    scanf (", %d", &x);
            if (x <= t) a[++cnt] = x;
        }
        memset (dp, 0, sizeof (dp));
        for (int i=1; i<=cnt; ++i)    {
            for (int j=1; j<=m; ++j)    {
                for (int k=0; k<=t; ++k)  {
                    dp[i][j][k] = dp[i-1][j][k];
                    if (k >= a[i])  {
                        dp[i][j][k] = max (dp[i][j][k], dp[i-1][j][k-a[i]] + 1);
                        dp[i][j][k] = max (dp[i][j][k], dp[i-1][j-1][t] + 1);
                    }
                }
            }
        }
        printf ("%d
", dp[cnt][m][t]);
        if (T)  puts ("");
    }

    return 0;
}

  

编译人生,运行世界!
原文地址:https://www.cnblogs.com/Running-Time/p/4773763.html