标签:
int n,K;
int a[MAX_N];
int m[MAX_N];
bool dp[MAX_N+1][MAX_N+1];
void solve()
{
dp[0][0] = true;
for(int i = 0 ; i < n ;i++){
for(int j = 0 ; j <= K; j++){
for(int k = 0 ; j <= m[i] && k *a[i] <= j ;k++){
dp[i+1][j] |= dp[i][j - k*a[i]];
}
}
}
if(dp[n][K]) printf("Yes\n");
else pritnf("No\n");
}
上述复杂度过高
O(nk)
定义:dp[i+1][j] 表示用前i种数加和得到j时第i种数最多能剩余多少个(不能加和得到i的情况下为-1)
m[i] (dp[i][j] >= 0)
动态转移方程 dp[i+1][j] = -1 (j < a[i] || dp[i+1][j-a[i]] <= 0)
int n,K;
int a[MAX_N];
int m[MAX_N];
int dp[MAX_K+1];
void solve()
{
memset(dp,-1,sizeof(dp));
dp[0] = 0;
for(int i = 0 ; i < n ;i++){
for(int j = 0 ; j <= K; j++){
if(dp[j] >= 0){
dp[j] = m[i];
}
else if(j < a[i] || dp[j-a[i]] <= 0){
dp[j] = -1;
}
else
dp[j] = dp[j-a[i]] - 1;
}
}
if(dp[K] >= 0) printf("Yes\n");
else printf("No\n");
}
AC代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int dp[121000];
int main()
{
int a[7] = {1,2,3,4,5,6};
int m[7];
int col = 1;
while(~scanf("%d%d%d%d%d%d",&m[0],&m[1],&m[2],&m[3],&m[4],&m[5])){
memset(dp,-1,sizeof(dp));
if(m[0] + m[1] + m[2] + m[3] + m[4] + m[5] == 0)
break;
printf("Collection #%d:\n",col++);
if((m[0] + m[1]*2 + m[2]*3 + m[3]*4 + m[4]*5 + m[5]*6)%2 == 1){
printf("Can‘t be divided.\n");
}
else {
int sum = (m[0] + m[1]*2 + m[2]*3 + m[3]*4 + m[4]*5 + m[5]*6)/2;
dp[0] = 0;
for(int i = 0; i < 6; i++){
for(int j = 0 ; j <= sum ;j++){
if(dp[j] >= 0) dp[j] = m[i];
else if(j < a[i] || dp[j-a[i]] <= 0){
dp[j] = -1;
}
else {
dp[j] = dp[j-a[i]] - 1;
}
}
}
if(dp[sum] >= 0)
printf("Can be divided.\n");
else printf("Can‘t be divided.\n");
}
puts("");
}
return 0;
}
标签:
原文地址:http://www.cnblogs.com/zero-begin/p/4539398.html