题目链接:

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4008

题目大意:

想象一下,你在KTV,想待久点,并且机器会让你唱完你歌再停。于是你选了劲歌金曲,678秒。现在你至少还剩一秒切到这首歌,而且每首歌必须唱完,现在问你你最久能待多久。

思路:

01背包,动态规划。但是01背包变式我第一次做的时候没有想到,结果误入歧途。。后面会贴代码,想直接看题解的不看便是,前面先说题解。

首先不断dp更新最大歌的数量,不算上劲歌金曲,然后用一个mx记录一下最大歌曲数量,注意,这里是为了限制你的决策。用时间作为背包容量进行dp,记录下最多歌曲数目,最后通过最多歌曲数目得出最多歌曲数目下的最长时间。至于为什么不能直接求,后面会给理由。

AC代码如下:

#include <iostream>
#include <string.h>
#include <cstdio>
#include <algorithm> using namespace std;
const int jingejinqu = ;
const int MX = 1e5+;
int dp[MX];
int v[MX]; int main()
{
int T;
scanf("%d", &T);
int k = ;
while(T--)
{
int summx = ;
memset(dp, -, sizeof(dp));
memset(v, , sizeof(v));
int n, m;
scanf("%d%d", &n, &m);
dp[] = ; //这里注意一下,刚开始从0开始,不然无法进行下去
for(int i = ; i <= n; ++i) scanf("%d", &v[i]);
for(int i = ; i <= n; ++i)
for(int j = m-; j >= v[i]; --j)
{
if(dp[j-v[i]] >= ) dp[j] = max(dp[j], dp[ j-v[i] ]+);
summx = max(summx, dp[j]);
}
for(int i = m-; i >= ; --i)
{
if(dp[i] == summx)
{
printf("Case %d: %d %d\n", ++k, summx+, i+jingejinqu);
break;
}
} }
}

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

下面是曲折的解题道路:

刚刚开始我直接当成了01背包裸题来解,思路也比较奇葩,就是直接解,定义了一个struct类来记录有没有选到:

#include <iostream>
#include <cstdio>
#define ll long long
#include <algorithm>
#include <string.h> using namespace std;
const int MX = 1e5+;
const int jinggejinqu = ;
ll dp[MX];
//ll val[MX]; struct {
ll x;
int flag;
} val[MX]; int main()
{
int T;
scanf("%d", &T);
int k = ;
while(T--)
{
memset(dp, -, sizeof(dp));
memset(val, , sizeof(val));
int cnt = ;
int n;
ll m;
scanf("%d%lld", &n, &m);
for(int i = ; i <= n; ++i) scanf("%lld", &val[i].x);
for(int i = ; i <= n; ++i)
{
ll x = dp[m];
for(int j = m-; j >= val[i].x; --j)
{
//dp[j] = max(dp[j], dp[ j-val[i] ]+val[i]);
if(dp[j] < dp[ j-val[i].x ]+val[i].x)
{
dp[j] = dp[ j-val[i].x ]+val[i].x;
//if(j == m) val[i].falg = 1;
}
else dp[j] = dp[j];
}
if(x+val[i].x == dp[m]) val[i].flag = ;
} for(int i = ; i <= n; ++i) if(val[i].flag) cnt++;
ll ans = dp[m]+jinggejinqu;
printf("Case %d: %d %lld\n", ++k, cnt, ans);
}
}

但是,WA了

后来继续想了个思路,2次dp:

#include <iostream>
#include <string.h>
#include <cstdio>
#include <algorithm> using namespace std;
const int jingejinqu = ;
const int MX = 1e7+;
int dp1[MX], dp2[MX];
int v[MX]; int main()
{
int T;
scanf("%d", &T);
int k = ;
while(T--)
{
int summx = ;
memset(dp1, -, sizeof(dp1));
memset(dp2, , sizeof(dp2));
memset(v, , sizeof(v));
int n, m;
scanf("%d%d", &n, &m);
dp1[] = ;
for(int i = ; i <= n; ++i) scanf("%d", &v[i]);
for(int i = ; i <= n; ++i)
for(int j = m-; j >= v[i]; --j)
{
if(dp1[j-v[i]] >= ) dp1[j] = max(dp1[j], dp1[ j-v[i] ]+);
summx = max(summx, dp1[j]);
}
for(int i = ; i <= n; ++i)
for(int j = m-; j >= v[i]; --j)
{
dp2[j] = max(dp2[j], dp2[ j-v[i] ]+v[i]);
}
printf("Case %d: %d %d\n", ++k, summx+, dp2[m-]+jingejinqu); }
}

还是WA了。。。

怎么也想不出哪里错了,于是百度,一看才知道:

下面取自博客:https://www.cnblogs.com/shi2015/p/4661971.html

由于要求是连续唱歌,且要求在最多歌曲数的情况下时间最长,如果按普通的背包存储,很难得到最长时间,因为f[len] 只存储了最多的歌曲数,但并不知道这些歌曲到底唱了多少时间。假设最多歌曲数为num, 唱num首歌曲最少时间为tmin, 那么数组中从f[tmin]到f[len]都等于num,我们无法得知唱num首歌的最大时间。比如说len = 10, t[1] = 5, t[2] = 8, 那么f[5] 到 f[10] 都等于1, 无法知道唱从5到10哪个是唱1首歌的最长时间。如何处理呢?

  这里需要用到一个技巧:对决策进行一定的限定!在计算某个时间最多唱的歌曲时,必须是该时间内恰好唱完这些歌,时间多了不行。即f[j]表示的是在j 的时间恰好用完的情况下最多能唱多少首歌。比如上面的例子只有f[5] 和f[8]等于1,其他的都等于0。这样的话处理时先算出最多唱的歌曲数 num,然后从j = len开始遍历数组f, 第一个等于num的就是在最多歌曲情况下的最长时间。

理解起来就是同样数量的值可能会在dp中出现多次所以,歌曲优先级大于时间,于是我们将歌曲数作为背包收益。

如有疑问,欢迎评论指出!

一道令人抓狂的零一背包变式 -- UVA 12563 Jin Ge Jin Qu hao的更多相关文章

  1. UVA - 12563 Jin Ge Jin Qu hao (01背包)

    InputThe first line contains the number of test cases T (T ≤ 100). Each test case begins with two po ...

  2. vue关闭令人抓狂的ESlint 语法检测配置方法

    随便改个vue 一堆报错 其实我并不反对这些语法检测,但是像许多反个人意愿的那就真的不得不吐槽了,比如vue-cli脚手架创建的默认eslint规则: 代码末尾不能加分号 ; 代码中不能存在多行空行 ...

  3. python 令人抓狂的编码问题

    #运行以下程序: #! /usr/bin/env python#coding=utf-8 file = open( 'all_hanzi.txt','wb' ) listhz = []n=0for c ...

  4. 令人抓狂的redis和rediscluster Python驱动包的安装

    本文环境:centos 7,Python3编译安装成功,包括pip3,然后需要安装redis相关的Python3驱动包,本的redis指redis包而非redis数据库,rediscluster类似. ...

  5. uva12563 Jin Ge Jin Qu hao(01背包)

    这是一道不错的题.首先通过分析,贪心法不可取,可以转化为01背包问题.但是这过程中还要注意,本题中的01背包问题要求背包必须装满!这就需要在普通的01背包问题上改动两处,一个是初始化的问题:把dp[0 ...

  6. UVa 12563 (01背包) Jin Ge Jin Qu hao

    如此水的01背包,居然让我WA了七次. 开始理解错题意了,弄反了主次关系.总曲目最多是大前提,其次才是歌曲总时间最长. 题意: 在KTV房间里还剩t秒的时间,可以从n首喜爱的歌里面选出若干首(每首歌只 ...

  7. UVa 12563 Jin Ge Jin Qu hao【01背包】

    题意:给出t秒时间,n首歌分别的时间a[i],还给出一首长度为678的必须唱的劲歌金曲,问最多能够唱多少首歌(只要最后时间还剩余一秒,都可以将劲歌金曲唱完) 用dp[i]代表花费i时间时唱的歌的最大数 ...

  8. UVA - 12563 Jin Ge Jin Qu hao (01背包变形)

    此题应该注意两个点,首先背包容量应该缩减为t-1,因为最长的歌不超过三分钟,而劲歌金曲有678s,所以肯定要留出这个时间来.其次注意优先级,保证唱的歌曲数目最多,在此前提下尽可能的延长时间. 处理方法 ...

  9. Jin Ge Jin Qu hao UVA - 12563 01背包

    题目:题目链接 思路:由于t最大值其实只有180 * 50 + 678,可以直接当成01背包来做,需要考虑的量有两个,时间和歌曲数,其中歌曲优先级大于时间,于是我们将歌曲数作为背包收益,用时间作为背包 ...

随机推荐

  1. 072、一文搞懂各种Docker网络 (2019-04-17 周三)

    参考https://www.cnblogs.com/CloudMan6/p/7587532.html   前面各个小节我们学习了 Docker Overlay .Macvlan .Flannel.We ...

  2. 五十五、linux 编程——TCP 连接和关闭过程及服务器的并发处理

    55.1 TCP 连接和关闭过程 55.1.1 介绍 建立连接的过程就是三次握手的过程:客户端发送 SYN 报文给服务器,服务器回复 SYN+ACK 报文,客户机再发送 ACK 报文. 关闭连接的过程 ...

  3. vue全局变量的使用

    新建一个VUE文件,声明一个变量,并且把它export. 在main.js中引入,并声明. 在其他地方使用,直接this就可以了.

  4. jar包中File 文件找不到的异常分析与解决

    源链接: http://hxraid.iteye.com/blog/483115#comments 我们常常在代码中读取一些资源文件(比如图片,音乐,文本等等).在单独运行的时候这些简单的处理当然不会 ...

  5. luogu P5303 [GXOI/GZOI2019]逼死强迫症

    传送门 只有两行,考虑递推,设\(f_i\)为没有那两个\(1*1\)的,前\(i\)列的方案,可以发现一次可以放一个竖的或两个横的,也就是\(f_i=f_{i-1}+f_{i-2}\) 再设\(g_ ...

  6. 解决select下拉框禁用(设置disabled属性),后台获取值为空

    如果下拉框设置disabled属性后,提交表单到后台,后台获取的下拉框的值为空,以下有三种解决获取不到下拉框选项值的方法. 有下拉框html如:<select name="select ...

  7. JAVA进阶18

    间歇性混吃等死,持续性踌躇满志系列-------------第18天 1.飞机游戏小项目 ①创建窗口 package cn.xfj.game; import javax.swing.*; import ...

  8. 关于this绑定的四种方式

    一.前言 我们每天都在书写着有关于this的javascript代码,似懂非懂地在用着.前阵子在看了<你不知道的JavaScript上卷>之后,也算是被扫盲了一边关于this绑定的四种方式 ...

  9. MySQL5.7开启独立表空间参数innodb_file_per_table【原创】

    今天在线上某个系统发现MySQL数据库使用的是共享表空间,想修改为独立表空间,操作如下: #因为是主从结构,在从库修改测试,先关闭binlog SET SQL_LOG_BIN=; show varia ...

  10. jssdk防覆盖

    防覆盖 var isFromTuia = (function () { var tuiaDomains = ['tuisnake', 'localhost'] function GetUrlDomai ...