ACM動態規劃模板(更新ing )

2021-08-18 19:27:30 字數 4472 閱讀 7410

1、最長上公升子串行問題

題目:有乙個長為n的數列a0,a1,…,an-1。請求出這個序列中最長的上公升子串行的長度。上公升子串行指的是對於任意的 i< j 都滿足ai< aj 的子串行。

思路:定義dp[i]為長度為i+1的上公升子串行中末尾元素的最小值(不存在的話為inf)

//最長上公升子串行問題

int dp[max_n];

void solve()

4、多重揹包問題

題目:有n種重量、價值和數量分別為wi,vi,ci的物品,從這些物品中挑選出總重量不超過w的物品,求出挑選物品價值總和的最大值。(1≤n≤100,1≤w≤50000)

**思路:**二進位制優化多重揹包。

//多重揹包問題

int n,w;

int w[max_n],v[max_n],c[max_n]; //重量、價值和數量

int dp[max_w];

void zeroone_pack(int w,int v)

void complete_pack(int w,int v)

int multi_pack()

}if(dp[k]>=0)return true;

else return false;

}

6、劃分數問題

題目:有n個無區別的物品,將它們劃分成不超過m組,求出劃分方法數模m的餘數。(1 ≤m≤n≤1000)

思路:考慮n的m劃分ai(i=1,2,3…),如果對於每個ai>0,那麼就對應了n-m的m劃分,另外如果存在ai=0,那麼就對應了n的m-1劃分。定義dp[i][j]為 i 的 j 劃分的總數,則dp[i][j]=dp[i][j-1]+dp[i-j][j]。

//劃分數問題

int n,m;

int dp[max_n][max_m];

void solve()

}printf("%d\n",dp[n][m]);

}

7、多重集組合數問題

題目:有n種物品,第i種物品有ai個。不同種類的物品可以互相區分但相同種類的無法區分。從這些物品中取出m個的話,有多少種取法?求出方案數模m的餘數。(1≤n≤1000,1≤m≤1000,1≤ai≤1000,2≤m≤10000)

思路:定義dp[i][j]為從前i中物品中取出j個的組合總數。

當j≤a[i]時,dp[i][j]=dp[i-1][j]+dp[i-1][j] 2. 當j>s[i]時,dp[i][j]=dp[i-1][j]+dp[i-1][j]-dp[i-1][j-1-a[i]]。

//多重集組合數問題

int n,m;

int dp[2][max_n];

void solve()

}printf("%d\n",dp[n&1][m]);

}

8、最大子矩陣和問題

題目:乙個n*m的矩陣,找到此矩陣的乙個子矩陣,並且這個子矩陣的元素的和是最大的,輸出這個最大的值。如果所有數都是負數,就輸出0。(2 <= n,m <= 500)

思路:最後的子矩陣一定在某兩行之間,列舉所有1<=i<=j<=n,表示最終子矩陣選取的行範圍。分別求出第i行到第j行之間的每一列的和,第i行到第j行之間的最大子矩陣和對應於這個和陣列的最大子段和。

//最大子矩陣和問題

int n,m;

int sum[max_m];

int map[max_n][max_m];

void solve()}}

printf("%d\n",max);

}

9、區間dp問題

[題目]:

n堆石子擺成一條線。現要將石子有次序地合併成一堆,規定每次只能選相鄰的2堆石子合併成新的一堆,並將新的一堆石子數記為該次合併的代價。計算將n堆石子合併成一堆的最小代價。

[普通解法]:

狀態轉移方程:f(i

,j)=

min+

w(i,

j)

f(i,j)=min\+w(i,j)

f(i,j)

=min

+w(i

,j)f(i

,j

)f(i,j)

f(i,j)

表示區間[i,

j]

[i,j]

[i,j

]上的最優值,w(i

,j

)w(i,j)

w(i,j)

表示轉移時付出的代價。

複雜度:o(n3)

#include#include#include#includeusing namespace std;

const int inf=0x3f3f3f3f;

const int max_n=1100;

int n;

int a[max_n],sum[max_n];

int dp[max_n][max_n];

int main()

// 從小區間向大區間進行地推

for(int d=1;d[四邊形不等式優化]:

對於一般方程:f(i

,j)=

opt+

w(i,

j)

f(i,j)=opt\+w(i,j)

f(i,j)

=opt

+w(i

,j)如果w

ww函式滿足區間單調性和四邊形不等式性質,則f

ff函式也滿足四邊形不等式性質,具有決策單調性。

決策單調性:

定義s (i

,j

)s(i,j)

s(i,j)

為f (i

,j

)f(i,j)

f(i,j)

取得最優值時對應的決策點(即下標),則s(i,j-1)≤s(i,j)

優化方程:

f(i,j)=opt+w(i,j) s(i,j-1)≤k≤s(i+1,j),複雜度:o(n2)

#include#include#include#includeusing namespace std;

const int inf=0x3f3f3f3f;

const int max_n=1100;

int n;

int a[max_n],sum[max_n];

int s[max_n][max_n],dp[max_n][max_n];

int main()

// 從小區間向大區間進行地推

for(int d=1;d10、數字dp問題

思路:dp思想,列舉到當前位置pos,狀態為state(這個就是根據題目來的,可能很多,畢竟dp千變萬化)的數量(既然是計數,dp值顯然是儲存滿足條件數的個數)

typedef long long ll;

int a[20];

ll dp[20][state];//不同題目狀態不同

ll dfs(int pos,/*state變數*/,bool lead/*前導零*/,bool limit/*數字上界變數*/)//不是每個題都要判斷前導零

//計算完,記錄狀態

if(!limit && !lead) dp[pos][state]=ans;

/*這裡對應上面的記憶化,在一定條件下時記錄,保證一致性,當然如果約束條件不需要考慮lead,這裡就是lead就完全不用考慮了*/

return ans;

} ll solve(ll x)

return dfs(pos-1/*從最高位開始列舉*/,/*一系列狀態 */,true,true);//剛開始最高位都是有限制並且有前導零的,顯然比最高位還要高的一位視為0嘛

} int main()

}

66666666666666666666666666

ACM網路流模板(更新ing )

1 最大流 2 二分圖匹配 3 最小費用流 1 最大流 ff ek dinic演算法比較 2 最大流 dinic演算法 描述 dinic演算法總是尋找最短的增廣路,並沿著它增廣。與之相對,ek演算法執行完一次bfs增廣後,要重新從源點s開始尋找另一條增廣路,而在dinic演算法中,只需一次bfs就可...

leetcode之動態規劃(更新ing)

給定乙個整數陣列 有正數有負數 找出總和最大的連續數列,並返回總和。示例 輸入 2,1,3,4,1,2,1,5,4 輸出 6 解釋 連續子陣列 4,1,2,1 的和最大,為 6。高階 如果你已經實現複雜度為 o n 的解法,嘗試使用更為精妙的分治法求解。class solution def maxs...

題目總結 動態規劃 更新ing

待更新.動態規劃是通過拆分問題,定義問題狀態和狀態之間的關係,使得問題能夠以遞推 或者說分治 的方式去解決。以上摘自知乎。就停課以來做的題來看,除了那些根本不會的,要注意的大概有 1 明確狀態定義 2 考慮初始狀況 3 注意端點狀況 4 時間複雜度,時間複雜度,時間複雜度 洛谷p1850換教室 真的...