zoukankan      html  css  js  c++  java
  • hdu 4091 线性规划

    分析转自:http://blog.csdn.net/dongdongzhang_/article/details/7955136

    题意 :  背包能装体积为N,  有两种宝石, 数量无限, 不能切割。  分别为 size1   value 1 size2 value2

    问背包能装最大的价值?


    思路 : 线性规划问题。  有一组坑爹数据  100 3 3 7 7   一般的会输出 99     但是结果是 100  各10颗


    线性规划知识, x, y 分别为 取两种宝石的数量   目标函数 : z = v1 * x + v 2 * y;      K = -(v1 / v2);

    1.   x >= 0;

    2.   y >= 0;

    3.   s1 * x + s2 + y <= N;   k = - (s1 / s2);




    若  abs(K)  > abs (k)  那么 将相交与B。   若abs(K) ==  abs(k)  整条直线都可以。 若 abs(K) < abs(k) 相交与A

    其实   abs(K) = v1 / v2  >  abs(k) = s1 / s2   正好是 价值比的比较,   v1 / s1 > v2 / s2    ,v1价值大, 就应该  x  大些, 取1宝石多些。

    同理  价值相同  就应该 x, y 取什么都可以,  v2 价值大, 就应该 y 大些,  取2宝石多些。


    但是  宝石不能切割, 所以。 就形成了一个区域, 在最优解附近。 所以区域附近的点 需要枚举。

    不过有一个不变的是, 在两宝石的体积的最小公倍数内, 肯定取价值大。

    而在最小公倍外的,就要分别枚举。 不能盲目的取价值大。 

     比如一个例子,   20 4 5 6 8   答案是 26  = 2 * 5 + 2 * 8。  若只取价值大的, 会装不满。 没取到最优解。    

    4 与 6 的最小公倍数是 12.  那每一个12的体积  就应该取  2个  宝石2   因为宝石2价值大。

    剩余的8 就有取枚举, 0 * 5 + 1 * 6 , 或者  1 * 5 + 0 * 6,  或者 2 * 5 + 0 * 6   那么就取2个宝石1.  就能装满了, 并且价值最大。

    但是 如果是 15 4 5 6 8 的话,  那么按照这方法就会输出   16   只能取到  2个 宝石2  剩余3体积, 不能取到任意宝石。 

    答案应该是 18 = 2 * 5 + 1 * 8,   少取一个宝石2,腾出6体积,并 利用剩余的3体积的2体积 取两颗宝石1,价值更大。

    所以,面对这问题。  我们就应该至少腾出一个公倍数的空间才枚举。  不然就会出错。

     1 #include<stdio.h>
     2 #include<algorithm>
     3 using namespace std;
     4 long long gcd(long long da,long long xiao)
     5 {
     6     long long temp;
     7     while(xiao!=0)
     8     {
     9         temp=da%xiao;
    10         da=xiao;
    11         xiao=temp;
    12     }    
    13     return da;
    14 }    
    15 int main()
    16 {
    17     int iCase=0;
    18     int T;
    19     scanf("%d",&T);
    20     long long N,S1,V1,S2,V2;
    21     while(T--)
    22     {
    23         iCase++;
    24         scanf("%I64d%I64d%I64d%I64d%I64d",&N,&S1,&V1,&S2,&V2);
    25         long long tmp=S1*S2/gcd(S1,S2);
    26         long long res;
    27         long long tt=N/tmp;
    28         N=N%tmp;
    29         if(tt)
    30         {
    31             tt--;
    32             N+=tmp;
    33         }    
    34         res=max((tt)*(tmp/S1)*V1,(tt)*(tmp/S2)*V2);
    35         long long res2=0;
    36         if(S2>S1)
    37         {
    38             long long t;
    39             t=S1;S1=S2;S2=t;
    40             t=V1;V1=V2;V2=t;
    41         }    
    42         for(int i=0;i<=N/S1;i++)
    43         {
    44             if(res2<i*V1+(N-i*S1)/S2*V2)res2=i*V1+(N-i*S1)/S2*V2;
    45         }    
    46         res+=res2;
    47         printf("Case #%d: %I64d
    ",iCase,res);
    48     }    
    49     return 0;
    50 }
  • 相关阅读:
    lua 与 c 的相互调用
    平台认证 & HTTP 302 重定向
    1. 个人经验总结
    Java反编译
    1. 个人经验总结
    3. 技术专题
    Office
    工作机的目录组织
    Eclipse
    Eclipse中的Gradle集成
  • 原文地址:https://www.cnblogs.com/cnblogs321114287/p/4286913.html
Copyright © 2011-2022 走看看