1. 程式人生 > 實用技巧 >[kuangbin帶你飛]專題十二 基礎DP1 題解+總結

[kuangbin帶你飛]專題十二 基礎DP1 題解+總結

kuangbin帶你飛:點選進入新世界

文章目錄

目錄

1.Max Sum Plus Plus

原題連結:傳送門

2.Ignatius and the Princess IV

原題連結:傳送門

思路:hash儲存(感覺和dp沒啥關係啊。。)

#include<bits/stdc++.h>
using namespace std;
map<int, int>mp; int n, t;
int main() {
    freopen("in.txt", "r", stdin);
    ios::sync_with_stdio(false); cin.tie(0);
    while (cin >> n) {
        mp.clear();
        for (int i = 0; i < n; ++i) { cin >> t; mp[t]++; }
        for (auto &p : mp) {
            if (p.second >= (n + 1) / 2) { cout << p.first << endl; break; }
        }
    }
}

3.Monkey and Banana

原題連結:傳送門

解析:對於所給的磚塊可以有6種組合(即:長寬高打亂)所以最終的 $ index = 6 * n$

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1000;
struct node {
    int l, r, w;//長寬高
}a[maxn];

int n, r, w, l;

bool cmp(node &a, node &b) {
    if (a.l == b.l)return a.r < b.r;
    return a.l < b.l;
}

int dp[maxn];

int main() {
    freopen("in.txt", "r", stdin);
    ios::sync_with_stdio(false); cin.tie(0);
    int Case = 1;
    while (cin >> n && n) {
        int index = 1;
        for (int i = 0; i < n; ++i) {
            cin >> l >> r >> w;
            a[index].l = l, a[index].r = r, a[index++].w = w;
            a[index].l = r, a[index].r = l, a[index++].w = w;
            a[index].l = w, a[index].r = r, a[index++].w = l;
            a[index].l = l, a[index].r = w, a[index++].w = r;
            a[index].l = r, a[index].r = w, a[index++].w = l;
            a[index].l = w, a[index].r = l, a[index++].w = r;
        }
        sort(a + 1, a + index + 1,cmp);//根據長寬排序
        memset(dp, 0,sizeof dp);
        int ans = 0;
        for(int i = 1;i <= index;++i)
            for (int j = 1; j <= index; ++j) {
                if (a[i].r < a[j].r && a[i].l < a[j].l)
                    dp[j] = max(dp[j], dp[i] + a[j].w), ans = max(ans, dp[j]);
            }
        cout << "Case " << Case++ << ": maximum height = " << ans << endl;
    }
}

4.Doing Homework

HDU - 1074

解析:

先大致說說狀態壓縮,假設有三門作業a,b,c
那麼,abc都做完即111,111可由101,110,011任意一個來得到。而101可以從100或者001來得到,這就是狀態壓縮dp的一個基本的狀態轉移。

#include<bits/stdc++.h>
using namespace std;
const int N = 16;
struct Node
{
    char str[109];
    int want, need;
}node[N];

struct DP
{
    int now, sum, next, pos;
}dp[1 << N];

void put_ans(int x)
{
    if (dp[x].next != -1)
    {
        put_ans(dp[x].next);
        printf("%s\n", node[dp[x].pos].str);
    }
}

int main()
{
    freopen("in.txt", "r", stdin);
    int T;
    scanf("%d", &T);
    while (T--)
    {
        int n;
        scanf("%d", &n);
        for (int i = 0; i < n; i++)
            scanf("%s%d%d", node[i].str, &node[i].want, &node[i].need);
        dp[0].now = dp[0].sum = 0;
        dp[0].next = dp[0].pos = -1;
        int m = (1 << n) - 1;
        for (int i = 1; i <= m; i++)
        {
            dp[i].sum = 0x3f3f3f3f;
            for (int j = 0; j < n; j++)
            {
                if ((1 << j) & i)
                {
                    int k = i - (1 << j);
                    int v = dp[k].now + node[j].need - node[j].want;
                    v = max(v, 0);
                    if (dp[i].sum >= dp[k].sum + v)
                    {
                        dp[i].sum = dp[k].sum + v;
                        dp[i].now = dp[k].now + node[j].need;
                        dp[i].next = k;
                        dp[i].pos = j;
                    }
                }
            }
        }
        printf("%d\n", dp[m].sum);
        put_ans(m);
    }
    return 0;
}

5.Super Jumping! Jumping! Jumping!

HDU - 1087

解析:注意題目是嚴格上升子序列並不是連續上升子序列(導致我寫錯了轉移方程2333)

#include<bits/stdc++.h>
using namespace std;

#define ms(a,b) (a,b,sizeof a)

const int maxn = 1e3 + 10;
int dp[maxn], a[maxn];
int n;

int main() {
    freopen("in.txt", "r", stdin);
    ios::sync_with_stdio(false); cin.tie(0);
    while (cin >> n && n) {
        ms(dp, 0);
        for (int i = 0; i < n; ++i)
            cin >> a[i], dp[i] = a[i];

        int ans = 0;

        for (int i = 0; i < n; ++i)
        {
            for (int j = i + 1; j < n; ++j)
            {
            	if (a[j] > a[i])
                    dp[j] = max(dp[j], dp[i] + a[j]);
            }
            ans = max(ans, dp[i]);
        }
        cout << ans << endl;
    }
}

同樣是LIS模板題:最少攔截系統:傳送門

Piggy-Bank

HDU - 1114