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\n", dp[cnt][m][t]);
        if (T)  puts ("");
    }

    return 0;
}

  

时间: 2024-10-12 19:50:18

DP UVA 473 Raucous Rockers的相关文章

洛谷P2736 “破锣摇滚”乐队 Raucous Rockers

P2736 “破锣摇滚”乐队 Raucous Rockers 21通过 52提交 题目提供者该用户不存在 标签USACO 难度普及+/提高 提交  讨论  题解 最新讨论 暂时没有讨论 题目描述 你刚刚继承了流行的“破锣摇滚”乐队录制的尚未发表的N(1 <= N <= 20)首歌的版权.你打算从中精选一些歌曲,发行M(1 <= M <= 20)张CD.每一张CD最多可以容纳T(1 <= T <= 20)分钟的音乐,一首歌不能分装在两张CD中. 不巧你是一位古典音乐迷,不

状压DP UVA 11795 Mega Man&#39;s Mission

题目传送门 1 /* 2 题意:洛克人有武器可以消灭机器人,还可以从被摧毁的机器人手里得到武器,问消灭全部机器人的顺序总数 3 状态压缩DP:看到数据只有16,就应该想到状压(并没有).因为是照解题报告写的,代码里加点注释,省的以后忘记了 4 */ 5 /************************************************ 6 * Author :Running_Time 7 * Created Time :2015-8-8 10:41:28 8 * File Nam

状压DP UVA 10817 Headmaster&#39;s Headache

题目传送门 1 /* 2 题意:学校有在任的老师和应聘的老师,选择一些应聘老师,使得每门科目至少两个老师教,问最少花费多少 3 状压DP:一看到数据那么小,肯定是状压了.这个状态不好想,dp[s1][s2]表示s1二进制表示下至少有1位老师的科目集合 4 s2表示至少有2位老师的科目集合所花费的最小金额,状态转移方程(01):dp[t1][t2]=min(dp[t1][t2],dp[j][k]+c[i]); 5 j,k为当前两个集合,t1,t2为转移后的集合,另外求t1,t2用到了& |位运算

[luoguP2736] “破锣摇滚”乐队 Raucous Rockers(DP)

传送门 f[i][j]表示前i首歌放到前j个盘里最多能放多首 ntr[i][j]表示i~j中最多能放进一张盘中多少首歌 ntr数组可以贪心预处理出来. #include <cstdio> #include <iostream> #include <algorithm> #define N 21 #define max(x, y) ((x) > (y) ? (x) : (y)) int n, t, m; int a[N], b[N], ntr[N][N], f[N]

uva 473(dp)

题意:按创作时间给出n首歌每首歌的时间ti,然后按创作时间装到m个光盘内,给出光盘最大分钟数t,问m个光盘最多总共放多少首歌. 题解:对于每首歌都能够选或者不选,假设选择了这首歌,是否把这首歌当做第j张光盘的第一首歌. f[i][j][k]表示前i首歌放到第j张光盘里用分钟数是k的容量最多放多少首歌. f[i][j][k] = f[i - 1][j][k]表示要选这首歌 f[i][j][k] = max(f[i][j][k], f[i][j - 1][t] + 1)表示把这首歌当做第j张光盘的第

(DP) UVA 10003

F - Cutting Sticks Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Status Practice UVA 10003 Appoint description:  System Crawler  (2015-01-31) Description  Cutting Sticks  You have to cut a wood stick into pieces. The m

区间DP UVA 1351 String Compression

题目传送门 1 /* 2 题意:给一个字符串,连续相同的段落可以合并,gogogo->3(go),问最小表示的长度 3 区间DP:dp[i][j]表示[i,j]的区间最小表示长度,那么dp[i][j] = min (dp[j][k] + dp[k+1][i+j-1]), 4 digit (i / k) + dp[j][j+k-1] + 2)后者表示可以压缩成k长度连续相同的字符串 4.5 详细解释 5 */ 6 /*****************************************

usaco Raucous Rockers

第一遍洗了个01背包,居然骗过了7个测试点. 后来才发现没我想的那么简单. dp[i][j][k]为前i首放在前j张光盘上,占用了第j个光盘的k分钟所能装的歌的数量 /* ID: modengd1 PROG: rockers LANG: C++ */ #include <iostream> #include <stdio.h> #include <memory.h> using namespace std; int main() { freopen("rock

递推DP UVA 1366 Martian Mining

题目传送门 1 /* 2 题意:抽象一点就是给两个矩阵,重叠的(就是两者选择其一),两种铺路:从右到左和从下到上,中途不能转弯, 3 到达边界后把沿途路上的权值相加求和使最大 4 DP:这是道递推题,首先我题目看了老半天,看懂后写出前缀和又不知道该如何定义状态好,写不出状态转移方程,太弱了. 5 dp[i][j]表示以(i, j)为右下角时求得的最大值,状态转移方程:dp[i][j] = max (dp[i-1][j] + sum1[i][j], dp[i][j-1] + sum2[i][j])