挑战程序设计竞赛笔记_P55

 

//理解的时候一定要看打出来的表理解!!!

#include<cstdio>
#include<cstdlib>
#define max(a, b) a > b ? a : b
const int MAX_N = 100;
const int MAX_W = 10000;
int n, W, w[MAX_W], v[MAX_N], dp[MAX_N + 1][MAX_W + 1];
int rec1(int i, int j)
{
    memset(dp, -1, sizeof(dp));
    if (dp[i][j] >= 0)
        return dp[i][j];
    if (i == n)
        return 0;
    if (j < w[i])
        return dp[i][j] = rec1(i + 1, j);
    else
        return dp[i][j] = max(rec1(i + 1, j), rec1(i + 1, j - w[i]) + v[i]);
}
int rec2(int i, int j)
{
    memset(dp, -1, sizeof(dp));
    if (dp[i][j] >= 0)
        return dp[i][j];
    if (i == 0)
        return 0;
    if (j < w[i - 1])
        return dp[i][j] = rec2(i - 1, j);
    else
        return dp[i][j] = max(rec2(i - 1, j), rec2(i - 1, j - w[i - 1]) + v[i - 1]);
}
int arr1()
{
    memset(dp, 0, sizeof(dp));
    for (int i = n - 1; i >= 0; i--)
    {
        for (int j = 1; j <= W; j++)
        {
            if (j < w[i])
                dp[i][j] = dp[i + 1][j];
            else
                dp[i][j] = max(dp[i + 1][j], dp[i + 1][j - w[i]] + v[i]);
        }
    }
    return dp[0][W];
}
int arr2()
{
    memset(dp, 0, sizeof(dp));
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= W; j++)
        {
            if (j < w[i - 1])
                dp[i][j] = dp[i - 1][j];
            else
                dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - w[i - 1]] + v[i - 1]);
        }
    }
    return dp[n][W];
}
int arr3()
{
    //数组方法3,同2
    memset(dp, 0, sizeof(dp));
    for (int i = 0; i < n; i++)
    {
        for (int j = 1; j <= W; j++)
        {
            if (j < w[i])
                dp[i + 1][j] = dp[i][j];
            else
                dp[i + 1][j] = max(dp[i][j], dp[i][j - w[i]] + v[i]);
        }
    }
    return dp[n][W];
}
int arr4(){
    memset(dp, 0, sizeof(dp));
    for (int i = 0; i < n; i++){
        //这里从j=1开始不行!!因为dp[i+1][j+w[i]]中j=0是有用的!而之所以前面的那些个数组方法可以,是因为他们根本用不着j=0来推断右下的元素
        for (int j = 0; j <= W; j++){
            if (w[i] + j <= W){
                dp[i + 1][j + w[i]] = dp[i][j] + v[i];
            }
            dp[i + 1][j] = max(dp[i][j], dp[i + 1][j]);
            // if (w[i] + j <= W){
            //     dp[i + 1][j + w[i]] = max(dp[i + 1][j + w[j]], dp[i][j] + v[i]);
            // }//这个改动是不是666?
        }
    }
    return dp[n][W];
}
void print()
{
    printf(" i\\j");
    for (int i = 0; i <= W; i++)
        printf("%4d", i);
    putchar(10);
    for (int i = 0; i <= n; i++)
    {
        printf("%4d", i);
        for (int j = 0; j <= W; j++)
            printf("%4d", dp[i][j]);
        putchar(10);
    }
    putchar(10);
}
int main()
{
    freopen("E:/My/input.txt", "r", stdin);
    scanf("%d%d", &n, &W);
    for (int i = 0; i < n; i++)
        scanf("%d%d", w + i, v + i);

    printf("arr1:%d\n", arr1());
    print();

    printf("arr2:%d\n", arr2());
    print();

    printf("arr3:%d\n", arr3());
    print();

    printf("arr4:%d\n", arr4());
    print();

    // printf("rec1:%d\n", rec1(0, W));
    // print();

    // printf("rec2:%d\n", rec2(n, W));
    // print();

    return 0;
}

#include 
#define max(a, b) a > b ? a : b
const int MAX_N = 100;
const int MAX_W = 10000;
int n, W, w[MAX_W], v[MAX_N], dp[MAX_N + 1][MAX_W + 1];
int rec1(int i, int j)
{
    memset(dp, -1, sizeof(dp));
    if (dp[i][j] >= 0)
        return dp[i][j];
    if (i == n)
        return 0;
    if (j < w[i])
        return dp[i][j] = rec1(i + 1, j);
    else
        return dp[i][j] = max(rec1(i + 1, j), rec1(i + 1, j - w[i]) + v[i]);
}
int rec2(int i, int j)
{
    memset(dp, -1, sizeof(dp));
    if (dp[i][j] >= 0)
        return dp[i][j];
    if (i == 0)
        return 0;
    if (j < w[i - 1])
        return dp[i][j] = rec2(i - 1, j);
    else
        return dp[i][j] = max(rec2(i - 1, j), rec2(i - 1, j - w[i - 1]) + v[i - 1]);
}
int arr1()
{
    memset(dp, 0, sizeof(dp));
    for (int i = n - 1; i >= 0; i--)
    {
        for (int j = 1; j <= W; j++)
        {
            if (j < w[i])
                dp[i][j] = dp[i + 1][j];
            else
                dp[i][j] = max(dp[i + 1][j], dp[i + 1][j - w[i]] + v[i]);
        }
    }
    return dp[0][W];
}
int arr2()
{
    memset(dp, 0, sizeof(dp));
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= W; j++)
        {
            if (j < w[i - 1])
                dp[i][j] = dp[i - 1][j];
            else
                dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - w[i - 1]] + v[i - 1]);
        }
    }
    return dp[n][W];
}
int arr3()
{
    //数组方法3,同2
    memset(dp, 0, sizeof(dp));
    for (int i = 0; i < n; i++)
    {
        for (int j = 1; j <= W; j++)
        {
            if (j < w[i])
                dp[i + 1][j] = dp[i][j];
            else
                dp[i + 1][j] = max(dp[i][j], dp[i][j - w[i]] + v[i]);
        }
    }
    return dp[n][W];
}
int arr4(){
    memset(dp, 0, sizeof(dp));
    for (int i = 0; i < n; i++){
        //这里从j=1开始不行!!因为dp[i+1][j+w[i]]中j=0是有用的!而之所以前面的那些个数组方法可以,是因为他们根本用不着j=0来推断右下的元素
        for (int j = 0; j <= W; j++){
            if (w[i] + j <= W){
                dp[i + 1][j + w[i]] = dp[i][j] + v[i];
            }
            dp[i + 1][j] = max(dp[i][j], dp[i + 1][j]);
            // if (w[i] + j <= W){
            //     dp[i + 1][j + w[i]] = max(dp[i + 1][j + w[j]], dp[i][j] + v[i]);
            // }//这个改动是不是666?
        }
    }
    return dp[n][W];
}
void print()
{
    printf(" i\\j");
    for (int i = 0; i <= W; i++)
        printf("%4d", i);
    putchar(10);
    for (int i = 0; i <= n; i++)
    {
        printf("%4d", i);
        for (int j = 0; j <= W; j++)
            printf("%4d", dp[i][j]);
        putchar(10);
    }
    putchar(10);
}
int main()
{
    freopen("E:/My/input.txt", "r", stdin);
    scanf("%d%d", &n, &W);
    for (int i = 0; i < n; i++)
        scanf("%d%d", w + i, v + i);

    printf("arr1:%d\n", arr1());
    print();

    printf("arr2:%d\n", arr2());
    print();

    printf("arr3:%d\n", arr3());
    print();

    printf("arr4:%d\n", arr4());
    print();

    // printf("rec1:%d\n", rec1(0, W));
    // print();

    // printf("rec2:%d\n", rec2(n, W));
    // print();

    return 0;
}

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值