• UVA 12589 Learning Vector(01背包+贪心(微扰))


    题目链接

    题目大意

      给n个向量从中选出k个向量,使得它们首尾连接与x轴成的面积的2倍最大。

    解题思路

      首先我们观察图形可以发现,每新加一个向量,图像右上角的横纵坐标都会变化,而且计算面积的时候需要知道前面的纵坐标,所以我们可以dp图像的纵坐标,其值就是面积,然后取最大面积。既然是从n个数中选出k个数,很明显就是一个01背包模型。
      但是还没完,还要考虑添加的顺序问题,这里我们用微扰(临项交换)来解。设前面所选方案所得的高度为h,然后又选了两个坐标,分别是((x_i,y_i),(x_j,y_j)),我们计算出这个方案的结果,然后再交换两个坐标的顺序再计算一遍结果,让两个结果做差,发现结果和斜率有关。
      交换前面积(S_1 = 2(hx_i)+x_iy_i+2(h+y_i)x_j+x_jy_j)
      交换后面积(S_2 = 2(hx_j)+x_jy_j+2(h+y_j)x_i+x_iy_i)
      (S_1-S_2 = x_jy_i - x_iy_j)。显然,如果要第一个方案比二个更优就要把斜率大的放前面。

    代码

    const int maxn = 2500+10;
    const int maxm = 2e2+10;
    struct INFO {
        int x, y;
    } a[55];
    ll dp[55][2505]; int n, m, kase;
    int main() {
        int t; scanf("%d", &t);
        while(t--) {
            scanf("%d%d", &n, &m);
            int sum = 0;
            for (int i = 1; i<=n; ++i) {
                scanf("%d%d", &a[i].x, &a[i].y);
                sum += a[i].y;
            }
            clr(dp, -1); dp[0][0] = 0;
            sort(a+1, a+n+1, [](INFO a1, INFO a2) {return a2.x*a1.y>a1.x*a2.y;});
            ll ans = 0;
            for (int i = 1; i<=n; ++i)
                for (int j = m; j>=1; --j)
                    for (int k = sum; k>=a[i].y; --k) 
                        if (dp[j-1][k-a[i].y]>=0) {
                            dp[j][k] = max(dp[j][k], dp[j-1][k-a[i].y]+2LL*a[i].x*(k-a[i].y)+1LL*a[i].x*a[i].y);
                            ans = max(ans, dp[j][k]);
                        }
            printf("Case %d: %lld
    ", ++kase, ans);
        }
        return 0;
    }
    
  • 相关阅读:
    Eclipse用法和技巧二十六:浅谈快捷键
    Eclipse用法和技巧二十五:eclipse图标的含义
    Eclipse用法和技巧二十四:当git遇上eclipse
    Eclipse用法和技巧二十三:查看JDK源码
    Eclipse用法和技巧二十二:快速调整字体大小
    Eclipse用法和技巧二十一:工程的展示途径
    94. Binary Tree Inorder Traversal
    110. Balanced Binary Tree
    595. Big Countries
    720. Longest Word in Dictionary(important!!!about sort)
  • 原文地址:https://www.cnblogs.com/shuitiangong/p/13565804.html
Copyright © 2020-2023  润新知