首页 > 代码库 > 多重部分和问题
多重部分和问题
描述:
N种不同数字ai每种mi个,判断是否可以选择若干个使得和为K
N<=100,k<=100000,ai,mi<=100000,均大于零。
分析:
裸算法:
DP[I][K]=0..1——前i个物品是否可以组成K
for (int i=1;i<=n;i++)
for (int k=0;k<=K;k++)
if (Dp[i-1][k])
for (int c=0;c<=mi;c++)
Dp[i][k+c*ai]=1;
时间复杂度显然是n*k*mi sum i=1..n 十分巨大
因为如果使用DP求BOOL往往很浪费,放弃了许多可以利用的信息。
如果我们不仅仅求出能否得到目标,并且记录下来剩下来多少个,可以减小很大的复杂度。
改为DP[I][K]为前I组成K,第I可以剩下最多为多少。
for (int i=1;i<=n;i++)
for (int k=0;k<=K;k++)
if (k>=ai)
{
if (Dp[i-1][k])
{
//上一个已经可以构成
Dp[i][k]=mi;
}
if (Dp[i][k-ai])
{
//如果DP[I][K]可以构成,那么DP[I][K-AI]是必然可以构成的
Dp[i][k]=Dp[i][k-ai]-1;
}
}
else
{
Dp[i][k]=-1;
}
多重部分和问题