百度之星资格赛 1004 度度熊的午饭时光 DP 打印路径

  题目链接: http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?cid=774&pid=1004

  题目大意: 一个0-1背包, 需要输出路径

  解题思路: 0-1背包很好求, 输出路径以前没有做过.......就是记录更新位置, 然后通过数组的跳跃间距求出到底取的是哪些点......

  代码: 自己代码, 没AC, 是什么玄学BUG, 我也懒得改了

#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <map>
#include <cstring>
#include <iterator>
#include <cmath>
#include <algorithm>
#include <stack>
#include <deque>
#include <map>

#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1


const int maxn = 1e3 + 100;
using namespace std;
//const int INF = 0x3fffffff;
int score[maxn];
int cost[maxn];
int dp[maxn][maxn]; // 前i个花费<=j时的最高得分
int vis[maxn][maxn];
int temp[maxn];
int cnt;
int main() {
    int t;
    scanf( "%d", &t );
    for( int cases = 1; cases <= t; cases++ ) {
        cnt = 0;
        int B;
        int N;
        scanf( "%d%d", &B, &N );
        for( int i = 1; i <= N; i++ ) {
            scanf( "%d%d", score+i, cost+i );
        }
        memset(dp, 0, sizeof(dp));
        memset(vis, 0, sizeof(vis));
        if( N == 0 || B == 0 ) {
            printf( "Case #%d:
",cases );
            printf( "0 0
" );
            continue;
        }
        for( int i = 1; i <= N; i++ ) {
            for( int j = B; j >= 0; j-- ) {
                dp[i][j] = dp[i-1][j];
                if( j >= cost[i] ) {
                    if( dp[i-1][j-cost[i]]+score[i] > dp[i][j] ) {
                        dp[i][j] = dp[i-1][j-cost[i]]+score[i];
                        vis[i][j] = 1;
                    }
                }
            }
        }
        int ans = 0;
        int i = N, j = B;
        while (i > 0 && j > 0)
        {
            if (vis[i][j] == 1)
            {
                ans += cost[i];
                j -= cost[i];
            }
            i--;
        }
        printf( "Case #%d:
", cases );
        printf( "%d %d
", dp[N][B], ans );
        i = N, j = B;
        while (i > 0 && j > 0)
        {
            if (vis[i][j] == 1)
            {
                temp[cnt++] = i;
                j -= cost[i];
            }
            i--;
        }
        sort( temp, temp + cnt);
        for( int i = 0; i < cnt; i++ ) {
            if( i == 0 ) printf( "%d", temp[i] );
            else printf( " %d", temp[i] );
        }
        printf( "
" );
    }
    return 0;
}
View Code

  徐文栋的AC代码: 

#include <bits/stdc++.h>
using namespace std;

typedef pair<int, int> pii;
const int maxn = 110;
const int maxm = 1010;
int m, n;
int v[maxn], w[maxn];
int f[maxm];
int path[maxn][maxm];
vector<int> tmp;

signed main() {
    // freopen("in", "r", stdin);
    int T, _ = 1;
    scanf("%d", &T);
    while(T--) {
        memset(path, 0, sizeof(path));
        memset(f, 0, sizeof(f));
        tmp.clear();
        scanf("%d%d",&m,&n);
        for(int i = 1; i <= n; i++) {
            scanf("%d%d",&v[i], &w[i]);
        }
        for(int i = 1; i <= n; i++) {
            for(int j = m; j >= w[i]; j--) {
                if(f[j] < f[j-w[i]]+v[i]) {
                    f[j] = f[j-w[i]] + v[i];
                    path[i][j] = 1;
                }
            }
        }
        printf("Case #%d:
", _++);
        int tot1 = 0, tot2 = 0;
        for(int i = n, j = m; i >= 1; i--) {
            if(path[i][j]) {
                tot1 += v[i]; tot2 += w[i];
                tmp.push_back(i);
                j -= w[i];
            }
        }
        printf("%d %d
", tot1, tot2);
        sort(tmp.begin(), tmp.end());
        for(int i = 0; i < tmp.size(); i++) {
            printf("%d%c", tmp[i], i==tmp.size()-1?'
':' ');
        }
    }
    return 0;
}
View Code

  思考: 自己只会纯裸的0-1背包, 真的菜, 通过这道题又补了自己的知识点, 以后还是通过做题锻炼自己的思维,再补自己的知识点

原文地址:https://www.cnblogs.com/FriskyPuppy/p/7293959.html