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;
}

猜你喜欢

转载自blog.csdn.net/Lee_w_j__/article/details/83548344