题目链接: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;
}