ZOJ 1013 Great Equipment ---- DP

/***Zoj 1013 Great Equipment 

主要思路

   遍历所有可能的携带方案组合(x, y, z)其中, x 为携带的第0中设备数量,

   y为携带的第1种设备数量, z为携带的第2种设备数量。

   

   使用Dynamic progromming 来计算可能的携带方案 

****/

#include <cstdlib>

#include <iostream>

#include <cstring>

#define MAXN 101

#define MAXQUANTITY 501

using namespace std;



inline int maxSets(int x, int y, int z, int q[3])

{

       x = x/q[0]; y = y/q[1]; z = z/q[2];

       return x > y ? (y > z ? z : y) : (x > z ? z : x);

}

//前 i个车队带了x个第0种设备和 y个第1种设备后, 还能带的第2种设备数量 

int f[2][MAXQUANTITY][MAXQUANTITY]; 

int main(int argc, char *argv[])

{

    int n;

    int w[3], s[3], d[3], q[3];

    //商队能带的最大重量, 尺寸 

    int wt[MAXN], sz[MAXN];    

    

    //前i个车队带了x个第0种设备后 ,   还能带的第1种设备数量 

    int a[MAXN][MAXQUANTITY];

    

    

    int sx[MAXN];

    int value;

    int cases=1;

    while (true)

    {

          cin>>n;

          if (n == 0) break;

          for (int i = 0; i < 3; i++)

          cin>>w[i]>>s[i]>>d[i];

          cin>>q[0]>>q[1]>>q[2];

          cin>>value;

          

          /*计算前i个车队能带的第0种设备数量 */

          sx[0] = 0;

          for (int i = 1; i <= n; i++)

          {

              cin>>wt[i]>>sz[i];

              int x1, x2;

              sx[i] =  sx[i-1] + 

                (( x1 = wt[i]/w[0]) > (x2 = sz[i] / s[0]) ? x2 : x1);

          }

          //for (int i = 0; i <= n; i++

          

          /*计算前 i个车队在带了x种第0种设备后, 还能带的第一种设备数量 */

          memset(a[0], 0, sizeof(a[0]));

          for (int i = 1; i <= n; i++)

          {

              for (int x = 0; x <= sx[i]; x++)

              {

                  a[i][x] = 0;

                  //y: 第 i个车队带的第0种设备数量 

                  int y = 0;

                  if (x > sx[i-1]) y = x - sx[i-1];

                  for (; y <= sx[i] - sx[i-1]; y++)

                  {

                      int x1, x2;

                      int num1 = ( x1 = (wt[i] - y*w[0])/w[1] )  > ( x2 = (sz[i] - y*s[0])/s[1] )

                                    ? x2 : x1;

                      if ( a[i-1][x-y] + num1 > a[i][x])

                        a[i][x] = num1 + a[i-1][x-y];

                  }

              }

          }

          

//           for (int i = 0; i <= n; i++)

//          {

//              for (int x = 0; x <= sx[i]; x++)

//                cout<<a[i][x]<<" ";

//              cout<<endl;

//          }

          

          /*计算前i个车队在带了x种0设备, y种1设备后, 能带的2设备数量*/

         // for (int x = 0; x < MAXQUANTITY; x++)

          //  for (int y = 0; y < MAXQUANTITY; y++)

          f[0][0][0] = 0;

          for (int i = 1; i <= n; i++)

          {

              for (int x = 0; x <= sx[i]; x++)

              {

                  for (int y = 0; y <= a[i][x]; y++)

                  {

                      f[1][x][y] = 0;

                      int t0, t1;

                      int mx0 = ( t0 = wt[i]/w[0] ) > ( t1 = sz[i]/s[0] ) ? t1 : t0;

                      //x0 第i个车队带的0设备数量, x1第i个车队带的1设备数量 

                      int x0 = 0;

                      //当x总数超过前i-1个车队能带的0设备能力时, 第i车队应当至少带: 

                      if ( x > sx[i-1] ) x0 = x - sx[i-1];                      

                      for (; x0 <= mx0 && x0 <= x; x0++)

                      {

                          int mx1 = ( t0 = (wt[i] - x0*w[0])/w[1] ) > ( t1 = (sz[i] - x0*s[0])/s[1] )

                                     ? t1 : t0;

                          int x1 = 0;

                          if ( y > a[i-1][x - x0] ) x1 = y - a[i-1][x - x0];           

                          for (; x1 <= mx1 && x1 <= y; x1++)

                          {

                              int mx2 = ( t0 = (wt[i] - x0*w[0] - x1*w[1])/w[2] )

                               > ( t1 = (sz[i] - x0*s[0] - x1*s[1])/s[2] ) ? t1 : t0;

                               

                               if (f[1][x][y] < f[0][x-x0][y-x1] + mx2)

                                   f[1][x][y] = f[0][x-x0][y-x1] + mx2;

                              // cout<<"x-x0 = "<<x - x0<<endl;

                              // cout<<"y-x1  ="<<y - x1<<endl;

                              // cout<<"f[1][x][y] = "<<f[1][x][y]<<endl; 

                              // cout<<"f[0][x][y] = "<<f[0][x-x0][y-x1]<<endl;  

                          }

                      }

                  }

              }

              for (int x = 0; x <= sx[i]; x++)

                 for (int y = 0; y <= a[i][x]; y++)

                    f[0][x][y] = f[1][x][y];

           }

           //cout<<"Here!/n";

           //枚举遍历, 求最大值

           int max = 0, mm, kk;

           int xx, yy, zz;

           //bool flag = value > q[0]*d[0]+q[1]*d[1]+q[1]*d[2];

           //cout<<"sx[n]="<<sx[n]<<endl;

           //cout<<"a[n][0] = "<<a[n][0]<<endl;

           //cout<<f[0][0][0]<<endl;

           for (int x = 0; x <= sx[n]; x++)

              for (int y = 0; y <= a[n][x]; y++)

                 for (int z = 0; z <= f[0][x][y]; z++)

                 {

                               kk = maxSets(x, y, z, q);

                               xx = x - kk*q[0]; yy = y - kk*q[1];

                               zz = z - kk*q[2];

                               mm = xx*d[0] + yy*d[1] + zz*d[2] + kk*value;

                               if ( mm > max ) max = mm;

                 }

           if (cases > 1) cout<<endl;

           cout<<"Case "<<cases++<<": "<<max<<endl;

         

    }

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值