I - Installing Apps 贪心+01背包

I - Installing Apps 贪心+01背包

题目大意:

有n种手机软件,每一种软件的安装包大小是d,安装后的软件大小是s(删除了安装包),那么若有c的手机内存,最多能安装多少个手机软件

题解:

贪心,用微调法可以确定贪心的策略,也就是排序的依据。

微调法就是调整前后两个的顺序,来求需要的容量,越小的在越前面。

然后就是一个01背包,但是01背包写的好搓。

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxn = 550;
struct node{
    int d,s,id;
    node(int d=0,int s=0,int id=0):d(d),s(s),id(id){}
}e[maxn];
bool cmp(node a,node b){
    return max(a.s,a.d)-a.s>max(b.d,b.s)-b.s;
}
int dp[maxn][11000];
/**
dp[i][j] 表示对于前面i个物品,选择之后花费了j的容量下载的最大的数量
**/
vector<int>a;
int main(){
    int n,c;
    scanf("%d%d",&n,&c);
    for(int i=1;i<=n;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        e[i] = node(x,y,i);
    }
    sort(e+1,e+1+n,cmp);
    memset(dp,0xef,sizeof(dp));
    dp[0][0] = 0;
    int ans = 0,pos = 0,v = 0;
    for(int i=1;i<=n;i++){
        // printf("i = %d s = %d d = %d\n", i,e[i].s,e[i].d);
        for(int j=0;j<=c;j++){
            if(c-j>=e[i].s&&c-j>=e[i].d){
                // printf("j = %d\n", j);
                dp[i][j+e[i].s]=max(dp[i][j+e[i].s],dp[i-1][j]+1);
                // printf("dp[%d][%d]=%d\n", i,j+e[i].s,dp[i][j+e[i].s]);
                if(dp[i][j+e[i].s]>ans){
                    ans = dp[i][j+e[i].s];
                    pos = j+e[i].s;
                    v = i;
                }
            }
            dp[i][j] = max(dp[i][j],dp[i-1][j]);
        }
    }
    a.clear();
    while(v>0){
        if(dp[v][pos]==dp[v-1][pos-e[v].s]+1) pos = pos-e[v].s,a.push_back(e[v].id);
        v = v - 1;
    }
    printf("%d\n", ans);
    for(int i=a.size()-1;i>=0;i--) printf("%d ", a[i]);
    printf("\n");
}
posted @ 2020-10-05 11:05  EchoZQN  阅读(146)  评论(0编辑  收藏  举报