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;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值