2017-2018 Northwestern European Regional Contest (NWERC 2017) I - Installing Apps(貪心 + dp記錄路徑)

題目鏈接:http://codeforces.com/gym/101623

題目大意:現在有一個內存爲 c 的手機,要往這部手機裏裝app。

現在有 n 個app,每個app有兩個屬性:1、下載佔用內存(d);2、安裝佔用內存(s)。

如果要安裝第 i 個app,那麼手機中至少需要max(d[i],s[i])的內存,裝了這個app之後,手機的內存就會增加s[i]。

現在問要以什麼順序安裝才能安裝儘可能多的app,同時輸出安裝順序。

題目思路:本題由於每個app有下載佔用內存這個屬性,所以如果想儘可能地多安裝app,所以得先將d[i] - s[i]較大的app優先安裝,這樣在安裝相同app的前提下剩餘的內存和可安裝的app就會儘可能的大。那麼只要按照 d[i] - s[i] 從大到小排序之後,就可以將這個題目當成揹包問題來對進行求解,再開兩個數組記錄下選擇路徑即可。

具體實現看代碼:

#include <bits/stdc++.h>
#define fi first
#define se second
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pb push_back
#define MP make_pair
#define lowbit(x) x&-x
#define clr(a) memset(a,0,sizeof(a))
#define _INF(a) memset(a,0x3f,sizeof(a))
#define FIN freopen("in.txt","r",stdin)
#define IOS ios::sync_with_stdio(false)
#define fuck(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int>pii;
typedef pair<ll, ll>pll;
const int MX = 500 + 7;
const int maxn = 10000 + 7;

int n, c;
struct node {
    int d, s, sub;
    int id;

    bool operator<(const node &A)const {
        if (sub == A.sub) return s < A.s;
        return sub > A.sub;
    }
} a[MX];
int last[MX][maxn], dp[MX][maxn];
bool vis[MX][maxn];
vector<int>ver;

int main() {
    //FIN;
    scanf("%d%d", &n, &c);
    for (int i = 1; i <= n; i++) {
        scanf("%d%d", &a[i].d, &a[i].s);
        a[i].id = i;
        a[i].sub = a[i].d - a[i].s;
    }
    sort(a + 1, a + n + 1);
    for (int i = 1; i <= n; i++) {
        for (int j = 0; j <= c; j++)
            dp[i][j] = max(dp[i - 1][j], dp[i][j]);
        for (int j = 0; j <= c; j++) {
            if (j + max(a[i].d, a[i].s) <= c) {
                if (dp[i][j + a[i].s] < dp[i - 1][j] + 1) {
                    dp[i][j + a[i].s] = dp[i - 1][j] + 1;
                    last[i][j + a[i].s] = j;
                    vis[i][j + a[i].s] = 1;
                }
            }
        }
    }
    int ans = 0, cc = 0;
    for (int i = 1; i <= c; i++) {
        if (dp[n][i] > ans) {
            ans = dp[n][i];
            cc = i;
        }
    }
    printf("%d\n", ans);
    if (ans) {
        int now = n;
        while (cc > 0 && now > 0) {
            if (vis[now][cc]) {
                ver.pb(a[now].id);
                cc = last[now][cc];
            }
            now--;
        }
        for (int i = (int)ver.size() - 1; i >= 0; i--)
            printf("%d%c", ver[i], i == 0 ? '\n' : ' ');
    }
    return 0;
}

 

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