2018zstu新生赛 P1
1408: Baby Coins
时间限制: 1 Sec 内存限制: 128 MB
提交: 31 解决: 8
[提交] [状态] [讨论版] [命题人:admin]
题目描述
Baby 今天清点自己的百宝箱啦,箱子里有 n 种硬币,硬币的面值分别是:val[1],val[2],…,val[n],每种面值的硬币都恰好有 2 个。Baby 实在闲的太无聊了,他想从他所拥有的硬币中选出若干个,使得面值之和为 k。那么他的目标能否实现呢 ~
输入
每一组数据第一行都包含两个数字 n(n≤18),k(1≤k≤109)。n 代表箱子中所包含的硬币种数,k 代表 Baby 需要组成的金钱数额。接下来的一行代表 val[1],val[2],…,val[n]。(1≤val[i]≤ 107)
输出
如果Baby能组成金钱数额k,请输出Yes,否则输出No。
样例输入
2
2 10
3 4
3 9
1 2 10
样例输出
Case 1: Yes
Case 2: No
来源/分类
2018浙江理工大学新生赛
看似背包 其实不是 由于数据的特殊性(n很小 k很大),可以采取dfs枚举结果
这里采取了分前后两部分dfs的方式,独立地存储枚举结果,最后判断和是否为k。
判断过程暴力会超时,所以采用二分查找:在第一个结果元素中查找(k-第二个结果元素)
丑陋代码
#include
#include<string.h>
#include
using namespace std;
int t,o,i,j,a[20],all1[20000],all2[20000],n1,n2,k,n;
int search(int x)
{
int l=0,r=n1-1,mid;
while(l<r)
{
mid=(l+r)/2+1;
if(x>=all1[mid])l=mid;
if(x<all1[mid])r=mid-1;
}
if(xall1[l])return 1;else return 0;
}
int dfs(int x,int y,int s,bool f)
{
if(xy){if(f)all1[n1++]=s;else all2[n2++]=s;return 0;}
dfs(x+1,y,s+a[x],f);
dfs(x+1,y,s+2*a[x],f);
dfs(x+1,y,s,f);
}
int main()
{
cin>>t;
for(o=1;o<=t;o++)
{
memset(all1,0,sizeof(all1));
memset(all2,0,sizeof(all2));
cin>>n>>k;n1=0;n2=0;
for(i=1;i<=n;i++)cin>>a[i];
dfs(1,n/2+1,0,true);
dfs(n/2+1,n+1,0,false);
sort(all1,all1+n1);
bool flag=false;
for(i=0;i<n2;i++)
if(search(k-all2[i])) flag=true;
cout<<"Case “<<o<<”: ";
cout<<(flag?“Yes”:“No”)<<endl;
}
}