UVa 12563 Jin Ge Jin Qu hao

来源:互联网 发布:武汉丛林网络看书 编辑:程序博客网 时间:2024/05/19 18:12

题目链接:

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


#include <cstdio>#include <map>#include <utility>#include <cstring>using namespace std;// my_map[(i,j)]代表从第i,i+1, ..., n首歌选,得到小于总时间长度情况下的最多曲目和对应时间//map<pair<int,int>, pair<int, long long> > my_map;// 总时间长度int total_time = 0;// 曲目数目(不包括Jin Ge Jin Qu)int n;// time[i]代表第i首歌时间int time[60];pair<int, long long> get_time(int i, int j);// r_num/r_time[i][j]代表从第i,i+1, ..., n首歌选,得到小于总时间长度情况下的最多曲目和对应时间int r_num[60][10000];int r_time[60][10000];int main(){int T;scanf("%d", &T);int count = 0;while(count < T){//my_map = map<pair<int,int>, pair<int, long long> >();memset(r_num, -1, sizeof(r_num));scanf("%d%d", &n, &total_time);for(int i = 1; i <= n; i++)scanf("%d", &time[i]);// 计算结果pair<int,long long> result = get_time(1, total_time);printf("Case %d: %d %lld\n", count+1, result.first+1, result.second+678);count++;}return 0;}// 计算结果// 计算从第i首歌开始选,小于j时间的最多曲目和相应时间pair<int, long long> get_time(int i, int j){/*pair<int,int> this_p = pair<int,int>(i, j);if(my_map.find(this_p) != my_map.end())return my_map[this_p];*/if(r_num[i][j] != -1)return pair<int, long long>(r_num[i][j], r_time[i][j]);if(i == n){if(j <= time[n]){//my_map[this_p] = pair<int,long long>(0, 0);r_num[i][j] = 0;r_time[i][j] = 0;}else{//my_map[this_p] = pair<int,long long>(1, time[n]);r_num[i][j] = 1;r_time[i][j] = time[n];}//return my_map[this_p];return pair<int, long long>(r_num[i][j], r_time[i][j]);}pair<int, long long> result;pair<int,long long> r1 = get_time(i+1, j);if(j > time[i]){pair<int,long long> r2 = get_time(i+1, j-time[i]);r2.first++;r2.second = r2.second + time[i];if(r1.first > r2.first){//my_map[this_p] = r1;result = r1;}else if(r1.first < r2.first){//my_map[this_p] = r2;result = r2;}else{if(r1.second >= r2.second){//my_map[this_p] = r1;result = r1;}else{//my_map[this_p] = r2;result = r2;}}}else{//my_map[this_p] = r1;result = r1;}r_num[i][j] = result.first;r_time[i][j] = result.second;//return my_map[this_p];return result;}

首先需要想一下Jin Ge Jin Qu必定被选。

假设Jin Ge Jin Qu不被选,现在选择的歌曲是a1,a2, ..., ax.

假设a1至ax时间不超过t, 那么可以再选Jin Ge Jin Qu最优。

假设a1至ax时间超过t, 那么a1至ax-1时间不超过t,由于ax时间小于Jin Ge Jin Qu, 那么将ax替换为Jin Ge Jin Qu得到的解更优。


因为Jin Ge Jin Qu必被选,不妨设其为最后一首被选,那么必须保证从n首歌选得歌的总时间长度小于t.

问题转换为从n首歌选歌,总时间长度小于t的情况下选择最多曲目,并保证最多曲目情况下选择总时间最长的。

为01背包问题。关于01背包问题为什么不能用贪心做,需要思考一下反例,及其与能用贪心做的部分背包问题作对比。


题目设置t可以为10^9, 一开始用map超时,后来看书才知道题目有很隐蔽的提示使得t最多不超过180*n+678.


0 0
原创粉丝点击