牛客小白月赛23 奇怪的背包问题增加了(思维)

链接:https://ac.nowcoder.com/acm/contest/4784/H

题目描述

题意:有230 背包容量,有n个物品,每个物品体积ci=2k,求是否能恰好装满背包。

输入描述:

第一行,是一个正整数T(1 \le T \le 100000)T(1≤T≤100000),表示接下来要输入T组测试数据
接下来有T测试数据的输入,对于每组测试数据,输入格式如下:
第一行,一个整数m(1 \le m \le 100000, \sum m\le10^5)m(1≤m≤100000,∑m≤10 5)第二行,用空格隔开的m个非负整数,第i个数字是k_i (0 \le k_i < 30)k
i (0≤k i<30)

输出描述:

依次输出T行,按照输入数据的顺序依次给出每组测试数据的答案,对于一组测试数据:如果存在一种符合条件的方案,则输出一个长度为m的01串,从前往后的第i位如果是1表示原序列中第i个物品被选中装进背包,为0则表示这个物品不被选中。如果不存在符合条件的方案,请输出impossible

示例1

输入
2
4
29 1 28 28
7
0 0 1 2 3 4 15
输出
1011
impossible

思路:

我们要注意到这是二进制加法,即230== 229+229 == 229+228+228 == 228+228+228+228 ,我们可以发现二进制加法有一个特点,它不会一下子越过一个数,它是逐步上升的。例如:期望值:100(2),目标值:1000(2),不论我们以哪种加法到达1000(2),都需要经过期望值。在此题我们的期望值是230,目标值是背包物品的和,当且仅当目标值>=期望值有解。因此我们可以把物品ci按降序排列,能放的就放,若有解一定能找到背包恰好放满的解。

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
struct node{
    
    
	ll w;
	int flag;
};
node a[maxn];
inline int cmp(node a,node b)
{
    
    
	if(a.w==b.w)
	return a.flag>b.flag;
	return a.w>b.w;
}
int ans[maxn];
int main()
{
    
    
	int t,n;
	cin>>t;
	while(t--)
	{
    
    
		cin>>n;
		int tt;
		for(int i=1;i<=n;i++)
		{
    
    
			cin>>tt;
			a[i].w=1<<tt;
			a[i].flag=i;
		}
		sort(a+1,a+1+n,cmp);
		ll sum=1<<30;
		memset(ans,0,sizeof(ans));
		for(int i=1;i<=n;i++)
		{
    
    
			if(sum>=a[i].w)
			{
    
    
				sum-=a[i].w;
				ans[a[i].flag]=1;
			}
		}
		if(sum==0)
		{
    
    
			for(int i=1;i<=n;i++)
			{
    
    
				cout<<ans[i];
			}
			cout<<"\n";
		}
		else
		cout<<"impossible"<<endl;
	}
	return 0;
 } 

猜你喜欢

转载自blog.csdn.net/xiaolan7777777/article/details/105531556
今日推荐