題目鏈接: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;
}