HDU1069Monkey and Banana(DP)

题目连接

解题报告:

各种错误,各种纠正。。自我感觉对DP的理解入门些了。

第一种思路是从i结点出发所能达到的最大高度,状态转移方程为dp[i] = dim[i]+max{dp[j]}, 其中G[i][j]=1,即j能放在i上。

 AC代码如下:

View Code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXN 91

struct{
    int x, y, z;
}dim[MAXN*3];

int dp[MAXN], G[MAXN][MAXN], _index;

void _swap(int *a, int *b){
    int t = *a;
    *a = *b; *b = t;
}

void _sort(int *a, int *b, int *c){
    if(*a > *b) _swap(a, b);
    if(*a > *c) _swap(a, c);
    if(*b > *c) _swap(b, c);
}

int _max(int a, int b){
    return a > b ? a : b;
}

void _assi(int a, int b, int c){
    dim[_index].x = a;
    dim[_index].y = b;
    dim[_index++].z = c;
}

int d(int i){
    if(dp[i] > 0) return dp[i];
    int j;
    for(j=1; j<_index; j++){
        if(G[i][j]) dp[i] = _max(dp[i], d(j));
    }
    dp[i] += dim[i].z;
    return dp[i];
}

int main(){
    int cnt, n, i, j, x, y, z;
    cnt = 0;
    while(scanf("%d", &n) == 1 &&n != 0){
        _index = 1; cnt++;
        memset(G, 0, sizeof(G));
        memset(dp, 0, sizeof(dp));
        for(i=1; i<=n; i++){
            scanf("%d %d %d", &x, &y, &z);
            _sort(&x, &y, &z);
            _assi(x, y, z);
            if(z != y) _assi(x, z, y);  //这里赋值的同时去掉重复的。当然也可以不去。
            if(x != y) _assi(y, z, x);
        }
        for(i=1; i<_index; i++){
            for(j=1; j<_index; j++){
                if(dim[i].x > dim[j].x && dim[i].y > dim[j].y) G[i][j] = 1;
            }
        }
        for(i=1; i<_index; i++)
            dp[i] = d(i);
        int ans = 0;
        for(i=1; i<_index; i++) if(ans < dp[i]) ans = dp[i];
        printf("Case %d: maximum height = %d\n", cnt, ans);
    }
    return 0;
}

第二种是从到i结点所能达到的最大高度,状态转移方程为dp[i] = dim[i]+max{dp[j]}, 其中G[j][i] = 1,即i能放在j上。

首先,让在输入数据的时候要保证结构体中的x>=y,然后再对这些数据进行排序,如果两者之间的x相等, 就进行y的二级排序。如此就能保证能够盛放i的长方体如果存在的话那么一定在dim[0 ~ i-1]中。省去了G这个二维数组。

AC代码如下。

View Code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXN 91

struct Dim{
    int x, y, z;
}dim[MAXN*3];

int dp[MAXN], _index;

int _max(int a, int b){
    return a > b ? a : b;
}

void _assi(int a, int b, int c){
    dim[_index].x = a > b ? a : b;
    dim[_index].y = a > b ? b : a;
    dim[_index++].z = c;
}

int cmp(const struct Dim *a, const struct Dim *b){ //竟然能这么用。。
    if(a->x != b->x) return b->x - a->x;
    else return b->y - a->y;
}

int main(){
    int cnt, n, i, j, x, y, z, ans;
    cnt = 0;
    
    while(scanf("%d", &n) == 1 &&n != 0){
        _index = 0; cnt++;
        memset(dp, 0, sizeof(dp));
        
        for(i=0; i<n; i++){
            scanf("%d %d %d", &x, &y, &z);
            _assi(x, y, z); //这里没有排除3个数存在2个或者3个有重复数字的情况,不过不影响
            _assi(x, z, y);
            _assi(y, z, x);
        }
        qsort(dim, _index, sizeof(dim[0]), cmp);
        
        dp[0] = dim[0].z;
        for(i=1; i<_index; i++){    //dp
            ans = 0;
            for(j=i-1; j>=0; j--){
                if(dim[j].x > dim[i].x && dim[j].y >dim[i].y)
                    if(ans < dp[j]) ans = dp[j];
            }
            dp[i] = ans+dim[i].z;
        }
        ans = 0;
        for(i=0; i<_index; i++) if(ans < dp[i]) ans = dp[i];
        printf("Case %d: maximum height = %d\n", cnt, ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/tanhehe/p/2910650.html