hdu 3602 2012

来源:互联网 发布:信封设计软件 编辑:程序博客网 时间:2024/06/05 09:03

Hdu 3602 解题报告

2012

ProblemDescription

As weknow,2012 is coming,and the presidents of many countries have planned to boardthe airships.We also know that every president i will bring a[i] bodyguards tomake sure his safe,and he will pay b[i] billion dollars to U.N. We also knowthat some countries are more powerful than others,so if we have chose somecountries to board the ship,we mustmake the powerful countries board first,andmake sure that the bodyguards stay the same ship with his president.
Now,U.N has m ships. And every ship can only contain k people.So cannot holdall the people,but the U.N want to make more mongey .Make the most money forthe U.N,then the U.N will give Lazy Yangyang a chance to survive when 2012 iscoming.
Lazy Yangyang want to be safe so that he can inherit the job of ACM for the newworld.To make the dream come true,the acmers of the world are solving theproblem for Lady YY,and you are one of them………

 

Input

In the firstline there is an integer T, indicates the number of test cases. (T <= 10)
In each case, the first line contains three integers n,m and k. (0 <m<=n<=100,0<k<100000)
Then n line,every line has two integers a[i]、b[i],(0<=a[i]<100000,0<=b[i]<100)representing the bodyguards anddollars, ordered by their power,The first country is the most powerful country.

 

Output

Most moneythat U.N can get.

 

SampleInput

1

42 400

601

1801

1801

2601

 

SampleOutput

3

 

【解题思路】

      随便挑了一题,2012这个题目比较新颖一点。题目也比较好读。大意是世界末日,联合国有M条船,有N个国家来买船坐,每个国家的总统要带a[i]个人一起走,而且要在一条船上,那么一共就是a[i]+1个人,而且国家之间有区分,越强的国家可以先选择船,每艘船的人数都是k。每个国家坐船要给b[i]的钱,求联合国最多能赚多少钱。(都什么时候了,还要程序猿来处理最多能赚多少钱 = =

      最一开始的想法是分组背包,但是再看看题,是有顺序的坐船,就觉得不是分组背包,可能就是一题简单的贪心。不过看到数据范围我就知道这题也不是贪心了。比较重要的一点,当前选择坐船的这个国家,一点会选择靠前坐,如果有空位置一定会坐前面的船。直接贪心或者说穷举是2^N的复杂度。

      想到以前做的题目,当然是想了2个小时以后发现可以用价值来做背包,存坐的船的条数,或者是位置数,如果记船的条数,也要记最后一条船剩的位置数,所以不妨记总位置数。用opt[i][j]表示前i个国家上船之后,达到j的价值时所占的最小位置数。

      确定了可以区分情况的状态,就可以写方程了。

(1)               在当前t这个国家选择上船时,如果前t-1条船的最后一条船上还有剩余的位置,够这个国家上船,那么就上这条已有人的船。总位置数直接加上a[i]+1

(2)               如果没有足够的位置,就上一条新船,并且记录下新的剩余位置数。总位置需要加上a[i]及前面所有满船的位置数。

方程如下:

     Opt[i][j]=Max(opt[i-1][j],opt[i-1][j-b[i]]+a[i]+1||(opt[i-1][j-b[i]]/k+1)*k+a[i]+1)

 

Code:

#include<iostream>

#include<cmath>

using namespacestd;

 

 

      intT,n,m,k,i,j,c,a[101],x,y,b[101],opt[101][10010],TotalV;

 

int main()

{

      cin >> T;

      while (T--)

      {

           //init

           TotalV=0;

           cin >> n >> m >> k;

           i=0;

           while (n--)

           {

                 cin >> x >> y;

                 if (x+1<=k)

                 {

                      a[i]=x+1;

                      b[i]=y;

                      TotalV+=b[i];

                      i++;

                 }

           }

 

           n=i;

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

                 for (j=0;j<=TotalV;j++)

                      opt[i][j]=2000000000;

           opt[0][b[0]]=a[0];

 

           //DP

 

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

                 for (j=b[i];j<=TotalV;j++)

                 {

                      opt[i][j]=opt[i-1][j];

                      c=opt[i-1][j-b[i]];

                      if (k-c%k>=a[i])

                      {

                        if(opt[i][j]>c+a[i])

                            opt[i][j]=c+a[i];

                      }

                      else

                      {

                     

                            if (c%k==0)

                            {

                                  if(opt[i][j]>c+a[i])

                                       opt[i][j]=c+a[i];

                            }

                            else

                            {

                                  if(opt[i][j]>(c/k+1)*k+a[i])

                                  opt[i][j]=(c/k+1)*k+a[i];

                            }

                      }

                 }

 

           //out

 

           for (i=TotalV;i>=0;i--)

                 if (opt[n-1][i]<=m*k)

                 {

                      cout << i <<endl;

                      break;

                 }

      }

      return 0;

}

0 0
原创粉丝点击