HOJ 12893 Just Enough Space

Just Enough Space
Time Limit: 1000ms, Special Time Limit:2500ms, Memory Limit:65536KB
Total submit users: 7, Accepted users: 6
Problem 12893 : No special judgement
Problem description


Input


Output

one line with an integer: the number of GB you need to convert, or the string “FULL” if not enough diskspace can be freed.


Sample Input
3
2 500
500 500
4 2400
400 600 700 1000
2 1000
10 10
Sample Output
500
1300
FULL
Problem Source
BAPC preliminary 2013


题目意思是你现在有n个磁盘,每个磁盘有一种功能,可以变成他容量的3倍。然后,你现在所有的磁盘都装满了容量,现在又来了一个数据data,需要放进你的磁盘,问,选择那些磁盘扩容能够容纳data,并且扩大的容量最小,输出你选择扩容的磁盘容量的和。这个题目的规模极其有意思,你的磁盘最多100个,每个最大2000G。而新来的数据data最大1e9G。对于题目分析,每个磁盘如果扩容,那么就是增加了2倍的容量,对于这个容量选还是不选,问题就成了0-1背包了,初看,对于容量那么大,1e9,0-1背包想想就爆了,可是仔细看看题意,100*2000*2=400000G < 1e9呀,那么容量就缩小到了400000在0-1背包范围内了。可是HOJ TLE了,大数据也会TLE了。同学有个很巧的想法,把1-400000做数组下标,初始化为0,把扩容极其所有组合对应的下标标记1,最后,对data-400000里离data最近的为1的i就是解了。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#define rt return
#define sf scanf
#define pf printf
#define si(n) sf("%d",&n)
#define pi(n) pf("%d",n)
#define REP0(i,n) for(int i=0;i<(n);i++)
#define REP1(i,n) for(int i=1;i<=(n);i++)
#define REP(i,s,n) for(int i=s;i<=(n);i++)
#define db double
#define pb push_back
#define LL long long
#define INF 0x3fffffff
#define eps 1e-8
#define PI acos(-1)
#define maxn 400010
using namespace std;
int n,val;
int dp[maxn],a[2010];
int main(){
    #ifdef ACBang
//    freopen("in.txt","r",stdin);
    #endif
    int CAS;sf("%d",&CAS);
    while(CAS--){
        sf("%d%d",&n,&val);
        int sum=0;
        int MAX=-1;
        REP0(i,n){
            sf("%d",&a[i]);
            a[i]*=2;
            MAX=max(MAX,a[i]);
            sum+=a[i];
        }
        if(sum<val){pf("FULL\n");continue;}
        memset(dp,0,sizeof(dp));
        for(int i=0;i<n;i++){
            for(int v=val+MAX;v>=a[i];v--){
                //想想为什么最大的容量只需从val+MAX就可以了??
                dp[v]=max(dp[v],dp[v-a[i]]+a[i]);
            }
        }
        for(int i=val;i<=val+MAX;i++){//dp肯定是非递减的
            if(dp[i]>=val){
                pf("%d\n",dp[i]/2);
                break;
            }
        }
    }
    rt 0;
}
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#define rt return
#define sf scanf
#define pf printf
#define si(n) sf("%d",&n)
#define pi(n) pf("%d",n)
#define REP0(i,n) for(int i=0;i<(n);i++)
#define REP1(i,n) for(int i=1;i<=(n);i++)
#define REP(i,s,n) for(int i=s;i<=(n);i++)
#define db double
#define pb push_back
#define LL long long
#define INF 0x3fffffff
#define eps 1e-8
#define PI acos(-1)
#define maxn 400010
using namespace std;
int n,val;
int a[2010],b[maxn];
int main(){
    #ifdef ACBang
//    freopen("in.txt","r",stdin);
    #endif
    int CAS;sf("%d",&CAS);
    while(CAS--){
        sf("%d%d",&n,&val);
        int sum=0;
        REP0(i,n){
            sf("%d",&a[i]);
            a[i]*=2;
            sum+=a[i];
        }
        if(sum<val){pf("FULL\n");continue;}
        memset(b,0,sizeof(b));
        b[0]=1;
        for(int i=0;i<n;i++){
            for(int j=val;j>=0;j--){
                if(b[j]==1)
                    b[j+a[i]]=1;
            }
        }
        int i;
        for(i=val;i<maxn;i++){
            if(b[i]==1){
                pf("%d\n",i/2);
                break;
            }
        }
    }
    rt 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值