这个题 想了好几个法子 最终还是峰哥讲给我的。
对01背包的运用还是很生的。 01背包的原理无非就是 某一个东西 用或者不用两种选择
那在这一个题中 就是某一首歌, 唱或者不唱两种状态 在选择时候 使得 歌的个数尽量多的前提下,唱歌时间尽量接近 (时间限制 - 1),
这样 就可以满足条件了。 dp【i】【j】 i 是 唱了几首歌 , j 是 用了多长时间。 标记为1 再进行一次遍历 歌的个数 从 n开始遍历 时间 从 总时间 - 1 开始遍历
找到等于1的那个状态 就退出结束。
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <set>
#include <cmath>
#include <stack>
#include <queue>
#include <cstring>
using namespace std;
#define ll long long;
#define maxn 10000 + 10
#define INF 100000000
int dp[60][maxn] = {0};
int main (){
int n;
int counts = 0;
scanf("%d",&n);
while(n--){
int num,time;
int ti[maxn];
scanf("%d%d",&num,&time);
for(int i = 1; i <= num; i++)
scanf("%d",&ti[i]);
memset(dp,0,sizeof(dp));
sort(ti+1,ti+1+num);
dp[0][0] = 1;
for(int i = 1; i <= num ; i++){
for(int j = time-1 ; j >= 0 ; j--){
for(int k = 1; k <= i ; k++){
if(j - ti[i] >= 0 && dp[k-1][j - ti[i]]){
dp[k][j] = 1;
}
}
}
}
int x = 0,t = 0;
int flag = 0;
for(int i = num; i >= 1 ; i--){
for(int j = time-1; j >= 0 ;j--){
if(dp[i][j]){
x = i;
t = j;
flag = 1;
break;
}
}
if(flag)
break;
}
printf("Case %d: %d %d\n",++counts,x + 1,t+678);
}
return 0;
}
本文详细解析了一个01背包问题的实例,通过选择歌曲演唱与否的状态来满足特定的时间限制条件,利用动态规划的方法实现了最优解的求解。

被折叠的 条评论
为什么被折叠?



