這題是挑戰程式設計競賽上的。
題意:n個不同的數字,每個有xi個,要恰好組成k這個數是否可能.
如果單純用dp[i][j]表示前i種數,和為j是否可能,那麼轉移方程就是:
dp[i][j]=dp[i][j]||dp[i-1][j-k*a[i]] k=min(j/a[i],x[i])
複雜度為o(n^3)
如果利用多重揹包二進位制的思想把數字按照個數分成其他數字,則可以將複雜度降為o(n^2lg(n))
但是這個題是可以做到o(n^2)的。
具體方法是定義狀態dp[i][j]表示前i種數,和恰好為j時剩餘最多a[i]的數量。也就是說前面我們在推dp[i][j]時,只用到了dp[i-1][k]的值,但是其實在計算q
狀態轉移
dp[i][j]=x[i];(dp[i-1][j]>0)
dp[i][j]=dp[i][j-a[i]]-1;(dp[i][j-a[i]]>0)
dp[i][j]=-1;(dp[i][j-a[i]]<=0)
看到轉移方程於是可以變為一維。
**。
#include #include #include using namespace std;
const int maxn = 105;
const int maxk = 100005;
int dp[maxn][maxk]; //dp[i][j]表示前i個數 恰好和為j時 第i個數最多剩多少.
int f[maxk];
int main()
多重部分和問題
有 n 種物品,第i種物品的每個物品的價值是 ai 數目是 mi 判斷是否可以選擇若干數字使得價值和是k。1 n 100 1 ai,m i,10 5 1 k 105 看作揹包大小是k,物品的價值和體積都是ai 物品數目是 mi 的多重揹包。如果最大價值是 k 的話就是可以選出,否則便是不能選出。利用...
多重部分和問題
有n種不同大小的數字a i 每種各m i 個。判斷是否可以從這些數字之中選出若干使它們的和恰好為k。dp i 表示以a i 為末尾的最長上公升子串行的長度。include include include includeusing namespace std define maxn 10010 int...
多重部分和問題
有n種不同大小的數字a i 每種各m i 個。判斷是否可以從這些數字中選出若干使它們的和恰好為k。限制條件 1 n 100,1 a i m i 100000,1 k 100000 這個問題可以用dp求解,如何定義遞推式影響最後的時間複雜度。定義dp i 1 j 用前i 1種數字 數字的編號是從0到i...