東東開車了(01揹包回溯)

完整代碼

東東開車出去泡妞(在夢中),車內提供了 n 張CD唱片,已知東東開車的時間是 n 分鐘,他該如何去選擇唱片去消磨這無聊的時間呢

假設:

CD數量不超過20張
沒有一張CD唱片超過 N 分鐘
每張唱片只能聽一次
唱片的播放長度爲整數
N 也是整數
我們需要找到最能消磨時間的唱片數量,並按使用順序輸出答案(必須是聽完唱片,不能有唱片沒聽完卻到了下車時間的情況發生)

Input

多組輸入

每行輸入第一個數字N, 代表總時間,第二個數字 M 代表有 M 張唱片,後面緊跟 M 個數字,代表每張唱片的時長 例如樣例一: N=5, M=3, 第一張唱片爲 1 分鐘, 第二張唱片 3 分鐘, 第三張 4 分鐘

所有數據均滿足以下條件:

N≤10000
M≤20

Output

輸出所有唱片的時長和總時長,具體輸出格式見樣例

Sample input

5 3 1 3 4
10 4 9 8 4 2
20 4 10 5 7 4
90 8 10 23 1 2 3 4 5 7
45 8 4 10 44 43 12 9 8 2

Sample output

1 4 sum:5
8 2 sum:10
10 5 4 sum:19
10 23 1 2 3 4 5 7 sum:55
4 10 12 9 8 2 sum:45

解題思路

這個題和一般的01揹包相比,多了一個回溯過程,要求得到放到揹包中的物體。本題輸出可能會有多種形式,輸出任意一種即可。比如最後一組數據,可能會輸出43 2 sum:45。

回溯過程的實現就是考慮當前dp[x][y],如果dp[x][y]=dp[x-1][y],那就說明沒有選擇第x個物品,回溯x-1, y。如果dp[x][y]=dp[x-1][y-w[i]]+v[i],那麼就說明選擇了第x件物品,回溯x-1, y-w[i]。直到x和y有一方爲0就返回。

完整代碼

//#pragma GCC optimize(2)
//#pragma G++ optimize(2)
//#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <climits>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;

const int maxn=20+1;
const int maxm=10000+1;
int n,m,a[maxn],dp[maxn][maxm];
int getint(){
    int x=0,s=1; char ch=' ';
    while(ch<'0' || ch>'9'){ ch=getchar(); if(ch=='-') s=-1;}
    while(ch>='0' && ch<='9'){ x=x*10+ch-'0'; ch=getchar();}
    return x*s;
}
void find(int x,int y){//回溯
    if(x==0 || y==0) return;

    if(dp[x][y]==dp[x-1][y])//第x件物品沒有選擇
        find(x-1,y);
    else if(dp[x][y]==dp[x-1][y-a[x]]+a[x]){//選擇了
        find(x-1,y-a[x]);
        printf("%d ",a[x]);
    }
}
int main(){
    //ios::sync_with_stdio(false);
    //cin.tie(0);
    while(cin>>n>>m){
        for (int i=1; i<=m; i++)
            cin>>a[i];
        for (int i=1; i<=m; i++)//普通01
            for (int j=0; j<=n; j++){
                if(j>=a[i]) dp[i][j]=max(dp[i-1][j],dp[i-1][j-a[i]]+a[i]);
                else dp[i][j]=dp[i-1][j];
            }
        find(m,n);
        printf("sum:%d\n",dp[m][n]);
        memset(dp,0,sizeof(dp));
    }

    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章