Cod sursa(job #3254925)

Utilizator matei__bBenchea Matei matei__b Data 9 noiembrie 2024 10:23:15
Problema Problema rucsacului Scor 10
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.93 kb
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp> 
#include <ext/pb_ds/tree_policy.hpp> 
#define ll long long
#define ull unsigned long long
#define ld long double
#define chad char
#define mod 1'000'000'007
#define dim 100005
#define lim 1000000
#define BASE 31
#define NMAX 21'005
#define FOR(i,a,b) for(int i=(a); i<=(b); i++)
#define ordered_set tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update> 
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define nr_biti __builtin_popcount
using namespace __gnu_pbds; 
using namespace std;

ifstream fin("rucsac.in");
ofstream fout("rucsac.out");

int t=1;
int mx,n,gmax;
int ans;

struct obiect 
{
    int g,p;
    bool operator<(const obiect &other)
    {
        // p/g<other.p/other.g -> p*other.g < other.p*g
        return p*other.g<other.p*g;
    }
}a[5005];
int sp_g[5005],sp_p[5005];
int min_suff[5005];

int getsum(int st,int dr,int sp[])
{
    return sp[dr]-sp[st-1];
}

bool viabil(int pos,int curr_g,int curr_p)
{
    if(curr_g>gmax)
        return 0;
    if(curr_g+min_suff[pos]>gmax)
        return 0;
    if(curr_p+getsum(pos,n,sp_p)<ans)
        return 0;

    // alta estimata e sa fac greedy 
    int st=pos,dr=n;
    int u=0;
    while(st<=dr)
    {
        int mij=(st+dr)/2;
        if(getsum(pos,mij,sp_g)<=gmax-curr_g)
        {
            u=mij;
            st=mij+1;
        }
        else 
            dr=mij-1;
    }

    if(u<n)
    {
        int rest=gmax-curr_g-getsum(pos,u,sp_g);
            // a[u+1].p/a[u+1].g * rest
            // curr_p+getsum(pos,u,sp_p)+a[u+1].p/a[u+1].g*rest<ans
            // a[u+1].g*(curr_p+getsum(pos,u,sp_p)+a[u+1].p*rest)<ans*a[u+1].g

        if(a[u+1].g*(curr_p+getsum(pos,u,sp_p)+a[u+1].p*rest)<a[u+1].g*ans)
            return 0;
    }
    else 
    {
        if(curr_p+getsum(pos,n,sp_p)<ans)
            return 0;
    }

    return 1;
}

void back(int pos,int curr_g,int curr_p)
{
    if(curr_g<=gmax)
        ans=max(ans,curr_p);

    if(!viabil(pos,curr_g,curr_p))
        return;

    if(pos==n+1)
        return;
    else 
    {
        if(a[pos].g+curr_g<=gmax)
            back(pos+1,a[pos].g+curr_g,curr_p+a[pos].p);
        back(pos+1,curr_g,curr_p);
    }
}

void solve()
{
    fin >> n >> gmax;
    for(int i=1; i<=n; i++)
        fin >> a[i].g >> a[i].p;
    
    sort(a+1,a+1+n);
    for(int i=1; i<=n/2; i++)
        swap(a[i],a[n-i+1]);
    
    for(int i=1; i<=n; i++)
    {
        sp_g[i]=sp_g[i-1]+a[i].g;
        sp_p[i]=sp_p[i-1]+a[i].p;
    }
    min_suff[n]=a[n].g;
    for(int i=n-1; i>=1; i--)
        min_suff[i]=min(min_suff[i+1],a[i].g);

    ans=0;
    back(1,0,0);
    fout << ans << "\n";
}

int main()
{
    ios_base::sync_with_stdio(false);
    fin.tie(nullptr);
    fout.tie(nullptr);

    //fin >> t;
    while(t--)
        solve();

    return 0;
}