USACO Subset 整數劃分01揹包

2022-04-14 14:11:14 字數 1893 閱讀 5386

又是去理解了一次01揹包。

這道題目的意思就是給你乙個n (n < 40)表示有乙個集合

你要將它劃分成相等的兩個子集合,求有幾種劃分方式

如果n是奇數,那麼顯然不能由相同的兩個sub sum組成,所以要輸出「0」

現在我們定義乙個陣列dp[i][j] 表示前i個數組合起來的和是j的種數

接下來就和01揹包很像了

得到狀態轉移方程dp[i][j] = dp[i - 1][j] + dp[i - 1][j - i]

分表代表當前的i 取 和 不取

在每一層 j 的轉移下要倒著來,從(1 + n) * n / 2 / 2開始推到1 (如果是從左到右則會重複計算)

在輸出的時候要把答案除以2因為for every sub sum there're 2 sub sets

至此題目已解決。

source code:

/*

id: wushuai2

prog: subset

lang: c++

*///

#pragma comment(linker, "/stack:16777216")

//for c++ compiler

#include #include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define max(a,b) (((a) > (b)) ? (a) : (b))

#define min(a,b) (((a) < (b)) ? (a) : (b))

#define abs(x) (((x) > 0) ? (x) : (-(x)))

#define mod 1000000007

#define pi acos(-1.0)

using

namespace

std;

typedef

long

long

ll ;

typedef unsigned

long

long

ull ;

typedef unsigned

intuint

;typedef unsigned

char

uchar ;

template

inline void checkmin(t &a,t b)

template

inline void checkmax(t &a,t b)

const

double eps = 1e-7

;const

int m = 660000

;const ll p =10000000097ll ;

const

int inf = 0x3f3f3f3f

;const

int max_n = 20

;const

int maxsize = 101000000

;ll f[

2000

];int

main()

max /= 2

; f[

0] = 1

;

for(i = 1; i <= n; ++i)

}fout

<< f[max] / 2

<< endl;//

fin.close();

fout.close();

return0;

}

整數劃分(劃分dp)總結

寫了幾個題發現整數劃分是一類題,而不是一道題。具體題型 1 n相同元素放入m個相同的盤子 盤子允許為空 例題 放蘋果 poj 1664設dp i j 為 j 個元素放入i個盤子轉移方程 dp i j dp i 1 j 新新增乙個盤子,盤子為空 dp i j dp i j i i個盤子 各取出乙個 2...

整數劃分問題

整數劃分問題是乙個經典問題,幾乎在講演算法設計的書中都會講,下面把主要的思想給總結下。所謂整數劃分,就是將乙個正整數n劃分為一系列的正整數之和,如將n可以劃分為 1 我們該如何找出所有的劃分呢?我們可以先來看看整數劃分的規律 譬如正整數 6 劃分情況如下 6 5 14 2 4 1 1 3 3 3 2...

整數劃分問題

給定乙個自然數,分成k部分,a1,a2.的數的和,要求a1 a2.求有多少種?原理 整數n拆分成最多不超過m個數的和的拆分數,和n 拆分成最大不超過m的拆分數相等。根據這個原理,原問題就轉化成了求最大拆分為k的拆分個數與最大拆分為k 1的拆分個數的差 f n,k f n,k 1 f n k,k 如下...