多重部分和二进制优化

多重部分和问题
题目描述
有n中不同大小的数字ai,每种各mi个。判断是否可以从这些数字之中选出若干使他们的大小恰好为K.
限制条件
1<=n<=100
1<=ai,mi<=100000
1<=k<=100000
输入
多组数据。
第一行n。第二行不同的数字ai.第三行对应数字拥有的个数
输出
能挑选若干恰好和为K则输出“Yes”,反之输出“No”.
样例输入
1
3
3 5 8
3 2 2
17

样例输出

Yes



#include <stdio.h>
#include <string.h>
int dp[100005];
int a[105];
int m[105];
int main()
{
int t, i, j, z, n, k, ans;
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
for(i = 0; i < n; i++)
scanf("%d", &a[i]); 
for(i = 0; i < n; i++)
scanf("%d", &m[i]); 
scanf("%d", &k);
memset(dp, -0x3f, sizeof(dp));
dp[0] = 0;
for(i = 0; i < n; i++)
{
if(m[i] * a[i] >= k)
{
for(j = a[i]; j <= k; j++)
dp[j] = dp[j] > dp[j - a[i]] + a[i] ? dp[j] : dp[j - a[i]] + a[i];
}
else
{
ans = 1;
while(m[i] - ans >= 0)
{
for(j = k; j >= ans * a[i]; j--)
dp[j] = dp[j] > dp[j - ans * a[i]] + ans * a[i] ? dp[j] : dp[j - ans * a[i]] + ans * a[i];
m[i] -= ans;
ans <<= 1; 
}
if(m[i] > 0)
{
for(j = k; j >= m[i] * a[i]; j--)
dp[j] = dp[j] > dp[j - m[i] * a[i]] + m[i] * a[i] ? dp[j] : dp[j - m[i] * a[i]] + m[i] * a[i];
}
}
}
if(dp[k] == k)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}


猜你喜欢

转载自blog.csdn.net/ymy6666/article/details/52495362