J - Judgement Gym - 100917J

Posted 吃花椒的妙酱

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了J - Judgement Gym - 100917J相关的知识,希望对你有一定的参考价值。

传送门

题目大意:n个法官,每个法官有初始权利值ai,和限制p,当权利值和大于等于p时案件通过(每个法官可以选择是否赞同,赞同则累加权利值),现在更换评判方式,将权利值由ai改为bi,限制p改为q,询问两种评判方式是否等价。不等价则输出其中一种矛盾情况

思路:01背包

由于ai和bi是连在一起的,每个法官的状态有两种选和不选,最后我们关心的是权利和,不用具体到哪个法官。我们把ai作为体积,bi作为重量跑01背包,p作为背包最大体积,当dp[p-1] >=q时说明存在矛盾,不等价,如果等价反过来把q作背包体积,bi作为体积,ai作为重量,当dp[q-1]>=p时不等价。两次背包跑完都没矛盾的情况则等价。

对于不等价情况,我们要输出方案,所以要具体到背包物品的信息(01)。

跑背包的时候,我们一边用bitset记录背包状态即可。


#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <map>
#include <vector>
#include <queue>
#include <bitset>
using namespace std;
#define _for(i,a,b) for(int i=(a) ;i<=(b) ;i++)
#define _rep(i,a,b) for(int i=(a) ;i>=(b) ;i--)
#define mst(v,s) memset(v,s,sizeof(v))
#define pb push_back
#define IOS ios::sync_with_stdio(false)
#define int long long
#define all(v) v.begin(),v.end()
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define ls p<<1
#define rs p<<1|1
typedef long long ll;
const int N=1e6+10;
int n,q1,q2;
int a[N],b[N];
int dp[N];
bitset <105> bt[N];
signed main()
{
    ///!!!
//    freopen("data.txt","r",stdin);
    ///!!!
    IOS;
    cin>>n;
    cin>>q1;_for(i,1,n) cin>>a[i];
    cin>>q2;_for(i,1,n) cin>>b[i];

    //p-1为最大体积,跑01背包
    _for(i,1,n)
    {
        for(int j=q1-1 ;j>=a[i] ;j--)
        {
            if( dp[j] < dp[j-a[i]] + b[i])
            {
                dp[j] = dp[j-a[i]]+b[i];
                bt[j] = bt[j-a[i]];//bitset记录背包状态
                bt[j][i]=1;
            }
        }
    }
    if( dp[q1-1]>=q2 )//如果有p-1不通过,q通过的情况输出no
    {
        cout<<"NO"<<endl;
        _for(i,1,n)
        {
            if( bt[q1-1][i] ) cout<<1;
            else cout<<0;
        }
    }
    else
    {
        mst(dp,0);
        mst(bt,0);
        //调换pq跑01背包,以q2-1为最大体积
        _for(i,1,n)
        {
            for(int j=q2-1 ;j>=b[i] ;j--)
            {
                if( dp[j] < dp[j-b[i]]+a[i] )
                {
                    dp[j] = dp[j-b[i]]+a[i];
                    bt[j] = bt[j-b[i]];
                    bt[j][i]=1;
                }
            }
        }
        if( dp[q2-1] >= q1 )
        {
            cout<<"NO"<<endl;
            _for(i,1,n)
            {
                if( bt[q2-1][i] ) cout<<1;
            else cout<<0;
            }
        }
        else cout<<"YES"<<endl;
    }
}

以上是关于J - Judgement Gym - 100917J的主要内容,如果未能解决你的问题,请参考以下文章

Gym 101102J---Divisible Numbers(反推技巧题)

gym 101412

2016 USP-ICMC-Codeforces-Gym101063C-Sleep Buddies Gym101063F-Bandejao Gym101063J-The Keys

Gym 100917J---dir -C(RMQ--ST)

gym103117J. Ants

J - VAT Man Gym - 102040J