• ACM学习历程—UESTC 1218 Pick The Sticks(动态规划)(2015CCPC D)


    题目链接:http://acm.uestc.edu.cn/#/problem/show/1218

    题目大意就是求n根木棒能不能放进一个容器里,乍一看像01背包,但是容器的两端可以溢出容器,只要两端的木棒的重心还在容器中即可。

    首先由于木棒可以两端溢出、一端溢出和不溢出三种情况,所以有状态p(flag, v)表示溢出个数为flag的容量为v的情况下的最值。

    于是有:

    p[2][j] = max(p[2][j], p[2][j-a[i]]+v[i]);

    p[2][j] = max(p[2][j], p[1][j-a[i]/2]+v[i]); 

    p[1][j] = max(p[1][j], p[1][j-a[i]]+v[i]);

    p[1][j] = max(p[1][j], p[0][j-a[i]/2]+v[i]);

    p[0][j] = max(p[0][j], p[0][j-a[i]]+v[i]);

    然后处理j那一维类似于01背包应该从lena[i]/2,然后对j<a[i]的情况特判。

    不过到这里,还没结束,应该a[i]/2不一定是整除。

    所以可以先对所有的a[i]len乘上2,然后再进行运算。。。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    #define LL long long
    
    using namespace std;
    
    const int maxN = 1005;
    int n, len;
    int a[maxN], v[maxN];
    LL p[4][maxN<<2];
    
    void input()
    {
        scanf("%d%d", &n, &len);
        len <<= 1;
        for (int i = 0; i < n; ++i)
        {
            scanf("%d%d", &a[i], &v[i]);
            a[i] <<= 1;
        }
        memset(p, 0, sizeof(p));
    }
    
    void work()
    {
        if (n == 1)
        {
            cout << v[0] << endl;
            return;
        }
        for (int i = 0; i < n; ++i)
        {
            for (int j = len; j >= a[i]/2; --j)
            {
                if (j-a[i] >= 0)
                    p[2][j] = max(p[2][j], p[2][j-a[i]]+v[i]);
                p[2][j] = max(p[2][j], p[1][j-a[i]/2]+v[i]);
                if (j-a[i] >= 0)
                    p[1][j] = max(p[1][j], p[1][j-a[i]]+v[i]);
                p[1][j] = max(p[1][j], p[0][j-a[i]/2]+v[i]);
                if (j-a[i] >= 0)
                    p[0][j] = max(p[0][j], p[0][j-a[i]]+v[i]);
            }
        }
        cout << p[2][len] << endl;
    }
    
    int main()
    {
        //freopen("test.in", "r", stdin);
        int T;
        scanf("%d", &T);
        for (int times = 1; times <= T; ++times)
        {
            printf("Case #%d: ", times);
            input();
            work();
        }
        return 0;
    }
    View Code
  • 相关阅读:
    使用winmm.dll 获取麦克风声音数据
    什么是拆箱和装箱?
    C#窗体程序【用户控件-窗体】委托事件
    如何在网页标题栏加入logo图标?
    C#汉字转拼音帮助类
    JQuery中$.ajax()方法参数详解
    UEditor独立图片、文件上传模块
    SqlServer2008安装时提示重启计算机失败 解决办法
    如果说人生是自我编写的程序
    LINQ的Any() 方法
  • 原文地址:https://www.cnblogs.com/andyqsmart/p/5002575.html
Copyright © 2020-2023  润新知