例题9-5 UVA 12563 Jin Ge Jin Qu [h]ao (01 背包)

来源:互联网 发布:多益网络用户中心 编辑:程序博客网 时间:2024/06/05 09:16

题意不说了 说的很清楚!

思路:

留出1秒唱时长为678秒的劲歌金曲!

剩下的t - 1秒就是在n首歌曲中 选择使得 总时长最大!

每首歌肯定选一次,每首歌的时间就是重量!

01背包变形,就是在重量不超过t-1的情况下 选择的数量最多!


因为最后的情况会输出选择了几首歌!所以方程可以这么写:

dp[j] = max(dp[j],dp[j-w[i]]+1);

最后从t-1到0枚举,看哪个dp最大 这里的dp就是出现的次数,在记录下标i,这个i就是总时间了!


#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn = 10000 + 10;typedef long long ll;ll dp[maxn],w[maxn];int main(){int T,cnt=0,n,t;scanf("%d",&T);while(T--){memset(dp,-1,sizeof(dp));dp[0]=0;scanf("%d%d",&n,&t);for (int i = 0; i < n; ++i)scanf("%lld",&w[i]);for (int i = 0; i < n; ++i)for (int j = t-1; j >= w[i]; --j)dp[j] = max(dp[j],dp[j-w[i]]+1);ll ans = -1,MAX = -1;for (int i = t-1; i >= 0; --i){if (dp[i] > MAX){MAX = dp[i];ans = i;}}printf("Case %d: %lld %lld\n",++cnt,MAX+1,ans+678);}return 0;}

========================

复习后的代码:

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn = 10000 + 1;int dp[57][maxn];int main(){    int T,kase = 0;    scanf("%d",&T);    while(T--){        int n,C,w;        memset(dp,-1,sizeof dp);        dp[0][0] = 0;        scanf("%d %d",&n, &C);        --C;        for (int i = 1; i <= n; ++i){            scanf("%d", &w);            for (int j = 0; j <= C; ++j){                dp[i][j] = dp[i-1][j];                if (j >= w)dp[i][j] = max(dp[i][j],dp[i-1][j-w] + 1);            }        }        int ans = -1,pos;//        for (int i = 0; i <= C; ++i)printf("%d ",dp[n][i]);        for (int i = C; i >= 0; --i){            if (dp[n][i] > ans){                ans = dp[n][i];                pos = i;            }        }        printf("Case %d: %d %d\n",++kase, ans + 1, pos + 678);    }    return 0;}


0 0