1. 程式人生 > 其它 >[kungbin] 專題12 基礎DP

[kungbin] 專題12 基礎DP

01

04[和最大上升子序] E - Super Jumping! Jumping! Jumping!

題目:

給定n個數字,選出一組遞增子序列,使得和最大

分析:

把最長上升子序的遞推公式改成求和

程式碼:

#include <bits/stdc++.h>
using namespace std;
int n;
int a[1010];
int dp[1010];
void work()
{
//  cin >> n;
    for (int i = 1; i <= n; i ++ ) cin >> a[i], dp[i] = a[i];
    int ans = 0;
    for (int i = 1; i <= n; i ++ )
    {
        for (int j = 1; j < i; j ++ ) 
            if (a[i] > a[j])
                dp[i] = max(dp[i], dp[j] + a[i]);
        ans = max(ans, dp[i]);
    }
        
    
    cout << ans << endl; 
}
int main()
{
    while (cin >> n, n)
    {
        work(); 
    }    
    return 0;
}

  

05 [完全揹包求體積恰好為m的最小值] F - Piggy-Bank

題目:

如標籤一樣,完全揹包求提及恰好為m的最小值

分析:

注意初始化,dp[0] = 0, 其他的都是無窮大,這樣答案只能從0轉移來,不會從其他的地方轉移而來

程式碼:

#include <bits/stdc++.h>
using namespace std;
int n, m, mm, mmm;
int dp[10005];
void work()
{
    //使填裝揹包的體積恰好為m,且價值最低 
    cin >> mm >> mmm;
    m = mmm - mm;
    cin >> n;
    memset(dp, 0x3f, sizeof dp);
    dp[0] = 0;
    int w, v;
    for (int i = 1; i <= n; i ++ )
    {
        cin >> w >> v;
        for (int j = v; j <= m; j ++ ) 
            dp[j] = min(dp[j], dp[j - v] + w);
    }
    if (dp[m] != 0x3f3f3f3f) printf("The minimum amount of money in the piggy-bank is %d.\n", dp[m]);
    else puts("This is impossible.");
}
int main()
{
    int t; cin >> t;
    while (t -- ) work();
    return 0;
}