zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    How do I access arcobjects from python?
    Win7 打开或关闭Windows功能 窗口空白 解决方案(ZZ)
    解释什么叫工作
    电脑城奸商最怕顾客知道的十条经验
    25岁前你要学会放下的八样东西
    必看十大电影
    SQL Server 中查询非中文,非英文,非数字的特殊列
    CHARINDEX 和 PATINDEX
    主流开源数据库的技术特点点评
    information_schema.routines与sysobjects
  • 原文地址:https://www.cnblogs.com/shuitiangong/p/13565804.html
Copyright © 2011-2022 走看看