kuangbin专题十二:基础DP1

  先跳过几章,换换口味。

HDU1024 Max Sum Plus Plus

思路:经典DP题。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 1e6 + 5;
int s[maxn], dp[maxn], pre[maxn];

int main(){
    int n, m;
    while(scanf("%d%d", &m, &n) != EOF){
        memset(dp, 0, sizeof(dp));
        memset(pre, 0, sizeof(pre));
        for(int i = 1; i <= n; i++) scanf("%d", s + i);
        int maxx;

        for(int group = 1; group <= m; group++){
            maxx = -0x3f3f3f3f;
            for(int i = group; i <= n; i++){
                dp[i] = max(dp[i - 1] + s[i], pre[i - 1] + s[i]);
                pre[i - 1] = maxx;
                maxx = max(maxx, dp[i]);
            }
        }
        printf("%d\n", maxx);
    }
    return 0;
}
View Code

 

HDU1029 Ignatius and the Princess IV

思路:就喜欢DP题,代码量小。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

int main(){
    int n;
    while(scanf("%d", &n) != EOF){
        int cnt = 0, num = -1, val;
        while(n--){
            scanf("%d", &val);
            if(num != val){
                if(cnt > 0) cnt--;
                else cnt = 1, num = val;
            }
            else cnt++;
        }
        printf("%d\n", num);
    }
    return 0;
}
View Code

 

HDU1069 Monkey and Banana

思路:一个盒子放6次。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1e3 + 5;
int dp[maxn];

struct Cube{
    int w, l, h;
} cube[maxn];

bool cmp(Cube &x, Cube &y){
    if(x.w == y.w) return x.l < y.l;
    return x.w < y.w;
}

int main(){
    int n, T = 0;
    while(scanf("%d", &n) && n){
        int idx = 0;
        for(int i = 0; i < n; i++){
            int x, y, z;
            scanf("%d%d%d", &x, &y, &z);
            cube[idx++] = {x, y, z};
            cube[idx++] = {x, z, y};
            cube[idx++] = {y, x, z};
            cube[idx++] = {y, z, x};
            cube[idx++] = {z, x, y};
            cube[idx++] = {z, y, x};
        }
        sort(cube, cube + idx, cmp);
        memset(dp, 0, sizeof(dp));
        for(int i = 0; i < idx; i++) dp[i] = cube[i].h;

        for(int i = 0; i < idx; i++)
            for(int j = i - 1; j >= 0; j--){
                if(cube[i].w > cube[j].w && cube[i].l > cube[j].l)
                    dp[i] = max(dp[i], dp[j] + cube[i].h);
            }
        int ans = 0;
        for(int i = 0; i < idx; i++) if(dp[i] > ans) ans = dp[i];
        printf("Case %d: maximum height = %d\n", ++T, ans);
    }
    return 0;
}
View Code

 

HDU1074 Doing Homework

思路:状态压缩DP。这种题目我第一次见到是我弟出给我的,欺负我这个老同志,来骗,来偷袭。

 

HDU1087 Super Jumping! Jumping! Jumping!

思路:最长子序列。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1005;
int num[maxn], dp[maxn];

int main(){
    int n;
    while(scanf("%d", &n) && n){
        for(int i = 0; i < n; i++) scanf("%d", &num[i]);
        for(int i = 0; i < n; i++){
            dp[i] = num[i];
            for(int j = 0; j < i; j++)
                if(num[i] > num[j])
                    dp[i] = max(dp[i], dp[j] + num[i]);
        }
        int ans = 0;
        for(int i = 0; i < n; i++) ans = max(ans, dp[i]);
        printf("%d\n", ans);
    }
    return 0;
}
View Code

 

HDU1114 Piggy-Bank

思路:基础背包。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 10005;
int dp[maxn];

int main(){
    int T;
    scanf("%d", &T);
    while(T--){
        int E, F, P, W, N, tot;
        scanf("%d%d%d", &E, &F, &N);
        tot = F - E;
        memset(dp, 0x3f, sizeof(dp));
        dp[0] = 0;
        while(N--){
            scanf("%d%d", &P, &W);
            for(int i = W; i <= tot; i++)
                if(dp[i] > dp[i - W] + P)
                    dp[i] = dp[i - W] + P;
        }
        if(dp[tot] == 0x3f3f3f3f)
            printf("This is impossible.\n");
        else
            printf("The minimum amount of money in the piggy-bank is %d.\n", dp[tot]);
    }
    return 0;
}
View Code


HDU1176 免费陷阱

思路:從前往後,咦,輸入怎麽變成繁體了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 100005;
int dp[maxn][11];

int main(){
    int n;
    while(scanf("%d", &n) && n){
        int x, T, maxT = 0;

        memset(dp, 0, sizeof(dp));
        for(int i = 1; i <= n; i++){
            scanf("%d%d", &x, &T);
            dp[T][x] += 1;
            maxT = max(maxT, T);
        }
        for(int i = maxT; i >= 0; i--)
            for(int j = 0; j <= 10; j++){
                int tmp = 0;
                for(int k = -1; k <= 1; k++)
                    if(k + j >= 0 && k + j <= 10)
                        tmp = max(tmp, dp[i + 1][j + k]);
                dp[i][j] += tmp;
            }
        printf("%d\n", dp[0][5]);
    }
    return 0;
}
View Code

 

HDU1260 Tickets

思路:模板题。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 2005;
int dp[maxn];
int single[maxn], couple[maxn];

int main(){
    int T;
    scanf("%d", &T);
    while(T--){
        int k;
        scanf("%d", &k);
        for(int i = 1; i <= k; i++) scanf("%d", &single[i]);
        for(int i = 2; i <= k; i++) scanf("%d", &couple[i]);

        // dp
        dp[1] = single[1];
        for(int i = 2; i <= k; i++){
            dp[i] = min(dp[i - 1] + single[i], dp[i-2] + couple[i]);
        }
        int h = 8 + dp[k] / 3600, m = (dp[k] / 60) % 60, s = dp[k] % 60;
        printf("%02d:%02d:%02d ", h, m, s);
        if(h <= 12) printf("am\n");
        else printf("pm\n");
    }
    return 0;
}
View Code

 

HDU1257 最少拦截系统

思路:考虑每个发射高度的最多发射数量。

#include<iostream>
#include<cstring>
using namespace std;
const int maxn = 3e4 + 5;
int dp[maxn], h[maxn];

int main(){
    int n;
    while(cin >> n){
        for(int i = 1; i <= n; i++) cin >> h[i], dp[i] = 1;

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

 

HDU1160 FatMouse's Speed

思路:LIS,注意体重相同的情况。

#include<iostream>
#include<algorithm>
#include<stack>
#include<stdio.h>
using namespace std;
const int maxn = 1e4 + 5;

int dp[maxn];

struct Mouse{
    int w, s, id;
} mice[maxn];

bool cmp(Mouse& a, Mouse& b){
    if(a.w == b.w) return a.s > b.s;
    return a.w < b.w;
}

int main(){
    int cnt = 0;
    while (cin >> mice[cnt].w >> mice[cnt].s) {
        mice[cnt].id = cnt;
        dp[cnt++] = 1;
    }
    sort(mice, mice + cnt, cmp);

    int reslen = 0;
    for (int i = 0; i < cnt; i++) {
        for (int j = i + 1; j < cnt; j++) {
            if (mice[i].w != mice[j].w && mice[i].s > mice[j].s) {
                dp[j] = max(dp[j], dp[i] + 1);
            }
        }
        reslen = max(reslen, dp[i]);
    }

    stack<int> s;
    int current;
    for (int i = cnt - 1; i >= 0; i--) {
        if (s.empty()) {
            if (dp[i] == reslen) {
                current = i;
                s.push(mice[i].id);
            }
        }
        else {
            if (dp[current] - 1 == dp[i] && mice[i].w != mice[current].w && mice[i].s > mice[current].s) {
                current = i;
                s.push(mice[i].id);
            }
        }
    }

    cout << reslen << endl;
    while(s.size()) {
        cout << s.top() + 1 << endl;
        s.pop();
    }

    return 0;
}
View Code

 

POJ1015 Jury Compromise

 

POJ1458 Common Subsequence

思路:最长公共子序列。

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn = 1005;
int dp[maxn][maxn];

int main(){
    string s1, s2;
    while (cin >> s1 >> s2) {
        memset(dp, 0, sizeof(dp));
        for (int i = 0; i < s1.length(); i++) {
            for (int j = 0; j < s2.length(); j++) {
                if (s1[i] == s2[j]) dp[i+1][j+1] = dp[i][j] + 1;
                else {
                    dp[i+1][j+1] = max(dp[i+1][j+1], dp[i][j]);
                    dp[i+1][j+1] = max(dp[i+1][j+1], dp[i+1][j]);
                    dp[i+1][j+1] = max(dp[i+1][j+1], dp[i][j+1]);
                }
            }
        }
        cout << dp[s1.length()][s2.length()] << endl;
    }
    return 0;
}
View Code

 

POJ1661 Help Jimmy

思路:暴力DP。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn = 1005;
int n, x, y, mx;

struct Seg{
    int x1, x2, h;
} seg[maxn];

int Conn[maxn][2];
int dp[maxn][2];

bool fall(Seg& s, int xx, int hh){
    if(hh - s.h > mx)
        return false;
    return s.x1 <= xx && xx <= s.x2;
}

bool cmp(const Seg& a, const Seg& b){
    return a.h > b.h;
}

int main(){
    int t;
    cin >> t;
    while(t--){
        cin >> n >> x >> y >> mx;
        for(int i = 0; i < n; i++) cin >> seg[i].x1 >> seg[i].x2 >> seg[i].h;
        seg[n].x1 = seg[n].x2 = x, seg[n].h = y;

        sort(seg, seg + n + 1, cmp);

        memset(dp, 0x3f, sizeof(dp));
        memset(Conn, 0, sizeof(Conn));
        dp[0][0] = dp[0][1] = 0;

        for(int i = 0; i <= n; i++){
            for(int j = i + 1; j <= n; j++){
                if(fall(seg[j], seg[i].x1, seg[i].h)){
                    dp[j][0] = min(dp[j][0], dp[i][0] + seg[i].x1 - seg[j].x1);
                    dp[j][1] = min(dp[j][1], dp[i][0] + seg[j].x2 - seg[i].x1);
                    Conn[i][0] = 1;
                    break;
                }
            }
            for(int j = i + 1; j <= n; j++){
                if(fall(seg[j], seg[i].x2, seg[i].h)){
                    dp[j][0] = min(dp[j][0], dp[i][1] + seg[i].x2 - seg[j].x1);
                    dp[j][1] = min(dp[j][1], dp[i][1] + seg[j].x2 - seg[i].x2);
                    Conn[i][1] = 1;
                    break;
                }
            }
        }

        int res = 0x3f3f3f3f;
        for(int i = n; i >= 0; i--){
            if(seg[i].h > mx) break;
            if(!Conn[i][0]) res = min(res, dp[i][0]);
            if(!Conn[i][1]) res = min(res, dp[i][1]);
        }
        res += y;
        cout << res << endl;
    }
    return 0;
}
View Code

 

POJ2533 Longest Ordered Subsequence

思路:模板题。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn = 1005;
int a[maxn];

int dp[maxn];

int main(){
    int n;
    cin >> n;
    for(int i = 1; i <= n; i++){
        cin >> a[i];
        dp[i] = 1;
    }

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

 

POJ3186 Treats for the Cows

思路:区间DP。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn = 2005;

int  ary[maxn];
int dp[maxn][maxn];

int main(){
    int n;
    cin >> n;
    for(int i = 1; i <= n; i++) cin >> ary[i];

    for(int i = 1; i <= n; i++) dp[i][i] = ary[i] * n;

    for(int i = 1; i < n; i++){
        for(int j = 1; j + i <= n; j++){
            dp[j][j + i] = max(dp[j+1][j+i] + ary[j] * (n - i), dp[j][j+i-1] + ary[j+i] * (n - i));
        }
    }
    cout << dp[1][n] << endl;
    return 0;
}
View Code

 

HDU1078 FatMouse and Cheese

思路:记忆化搜索。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn = 105;
int n, k;
int dx[] = {1, 0, -1, 0}, dy[] = {0, 1, 0, -1};

int mm[maxn][maxn];
int dp[maxn][maxn];

bool inRange(int x, int y){
    return x >= 0 && y >= 0 && x < n && y < n;
}

void search(int x, int y){
    for(int i = 0; i < 4; i++){
        for(int j = 1; j <= k; j++){
            int nx = x + j * dx[i], ny = y + j * dy[i];
            if(inRange(nx, ny) && mm[x][y] < mm[nx][ny]){
                if(!dp[nx][ny])
                    search(nx, ny);
                dp[x][y] = max(dp[x][y], dp[nx][ny] + mm[x][y]);
            }
        }
    }
    dp[x][y] = max(dp[x][y], mm[x][y]);
}

int main(){
    while(cin >> n >> k && n != -1){
        memset(dp, 0, sizeof(dp));
        for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++)
                cin >> mm[i][j];

        search(0, 0);

        cout << dp[0][0] << endl;
    }
    return 0;
}
View Code

 

HDU2859 Phalanx

 思路:二维DP。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn = 1005;
int n;

char mm[maxn][maxn];
int dp[maxn][maxn];

int main(){
    while(cin >> n && n){
        for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++){
                cin >> mm[i][j];
                dp[i][j] = 1;
            }

        for(int i = 1; i < n; i++){
            for(int j = 0; j < n-1; j++){
                int len = dp[i-1][j+1];
                int k;
                for(k = 1; k <= len; k++)
                    if(mm[i-k][j] != mm[i][j+k]){
                        break;
                    }
                dp[i][j] = k;
            }
        }

        int res = 0;
        for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++)
                res = max(res, dp[i][j]);
        cout << res << endl;
    }
    return 0;
}
View Code

 

POJ3616 Milking Time

思路:离散化。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn = 1e3+5;
int n, m, r;
int dp[maxn];

struct Interval{
    int st, ed, eff;
} intv[maxn];

bool cmp(const Interval& a, const Interval& b){
    if(a.st == b.st) return a.ed < b.ed;
    return a.st < b.st;
}

int main(){
    cin >> n >> m >> r;
    for(int i = 0; i < m; i++){
        cin >> intv[i].st >> intv[i].ed >> intv[i].eff;
        intv[i].ed += r;
    }
    sort(intv, intv + m, cmp);

    for(int i = 0; i < m; i++){
        dp[i] = intv[i].eff;
        for(int j = 0; j < i; j++)
            if(intv[j].ed <= intv[i].st)
                dp[i] = max(dp[i], dp[j] + intv[i].eff);
    }

    int res = 0;
    for(int i = 0; i < m; i++) res = max(res, dp[i]);
    cout << res << endl;
    return 0;
}
View Code

 

POJ3666 Making the Grade

 思路:二维dp,注意别写成三维dp。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn = 2e3+5;
int n;
int A[maxn], B[maxn], C[maxn];
long long dp[maxn][maxn][2];

bool cmp(int a, int b){
    return a > b;
}

int main(){
    scanf("%d", &n);
    for(int i = 0; i < n; i++){
        scanf("%d", A+i);
        B[i] = C[i] = A[i];
    }
    sort(B, B + n);
    sort(C, C + n, cmp);

    memset(dp, 0x3f, sizeof(dp));

    dp[0][0][0] = abs(A[0] - B[0]);
    dp[0][0][1] = abs(A[0] - C[0]);

    for(int i = 1; i < n; i++){
        dp[0][i][0] = min(dp[0][i-1][0], (long long)abs(A[0] - B[i]));
        dp[0][i][1] = min(dp[0][i-1][1], (long long)abs(A[0] - C[i]));
        dp[i][0][0] = dp[i-1][0][0] + abs(A[i] - B[0]);
        dp[i][0][1] = dp[i-1][0][1] + abs(A[i] - C[0]);
    }

    for(int i = 1; i < n; i++){
        for(int j = 1; j < n; j++){
            dp[i][j][0] = min(dp[i-1][j][0] + abs(A[i] - B[j]), dp[i][j-1][0]);
            dp[i][j][1] = min(dp[i-1][j][1] + abs(A[i] - C[j]), dp[i][j-1][1]);
        }
    }


    long long res = 0x3f3f3f3f;
    for(int i = 0; i < n; i++) res = min(res, dp[n-1][i][0]), res = min(res, dp[n-1][i][1]);
    printf("%lld\n", res);

    return 0;
}
View Code

 

posted @ 2021-03-10 21:22  Nanachi  阅读(104)  评论(0编辑  收藏  举报