白菜芯的菜田

toj acm1057 piggy bank

题目如下:http://acm.tju.edu.cn/toj/showp1057.html

一开始苦思仍然没找到非枚举的方法,于是用枚举算了一遍,果不其然地超时了。

后来上网搜索后,看到一句提示,可以采用动态规划的方法。

由于题目要求中硬币数量和重量都为整数,可以做一个长度为硬币总重量+1的数组value[i],然后将其全部赋上最大值MAX,value[i]代表硬币总重量为i的情况下,最小可能的价值。然后用value[i]+v[j]去刷新value[i+w[j]]的值即可。相较于枚举来说,这样的方法消除了不同硬币组合产生相同重量的情形,节省了计算时间。

一开始写了一个递归函数去实现这个动态规划

代码
 1 void recur(int i, int moneyW, int coinAmount, int valueArray[], int coinV[], int coinW[])
 2 {
 3      for ( int j=0 ; j<coinAmount ; j++)
 4      {
 5          if( i+coinW[j] <= moneyW )
 6          {
 7              if( valueArray[i+coinW[j]] > valueArray[i] + coinV[j] )
 8              {
 9                  valueArray[i+coinW[j]] = valueArray[i] + coinV[j];
10                  recur(i+coinW[j], moneyW, coinAmount, valueArray, coinV, coinW);
11              }
12          }
13      }
14 }

 

将总的问题分为若干小的相同子问题,递归的方式比较直白,给定当前weight,然后用各种硬币去加,不幸又超时了。

这次换着用非递归的方法去求解,逐个处理valueArray[]中的每一个值,若valueArray[i]!=MAX,说明它已被刷新过值,计算valueArray[i+w[j]]对于每种硬币去刷新一遍valueArray

 

代码
 1 #include <iostream>
 2 #define MAX 600001
 3 using namespace std;
 4 
 5 int main()
 6 {
 7     int cas;
 8     cin>>cas;
 9     while( cas > 0 )
10     {
11            int pigW=0;
12            int wholeW=0;
13            int moneyW=0;
14            cin>>pigW;
15            cin>>wholeW;
16            moneyW = wholeW - pigW;
17            int valueArray[moneyW+1];
18            for ( int i=0 ; i< moneyW+1 ; i++ )
19                valueArray[i] = MAX;
20            int coinAmount = 0;
21            cin>>coinAmount;
22            int coinW[coinAmount];
23            int coinV[coinAmount];
24            for ( int i=0; i<coinAmount; i++ )
25            {
26                cin>>coinV[i];
27                cin>>coinW[i];
28            }
29            valueArray[0]=0;
30            //recur(0, moneyW, coinAmount, valueArray, coinV, coinW);
31            forint i=0; i<=moneyW ; i++)
32            {
33                 if(valueArray[i] != MAX)
34                 {
35                                  for(int j=0; j<coinAmount ; j++)
36                                  {
37                                          if(i+coinW[j]<=moneyW && valueArray[i+coinW[j]]>valueArray[i]+coinV[j])
38                                          {
39                                           valueArray[i+coinW[j]]=valueArray[i]+coinV[j];
40                                          }
41                                  }
42                 }
43            }
44            //for( int m=0; m<=moneyW ; m++)
45            //     cout<<valueArray[m]<<" ";
46            if ( valueArray[moneyW] == MAX )
47               cout<<"This is impossible."<<endl;
48            else
49                cout<<"The minimum amount of money in the piggy-bank is "<<valueArray[moneyW]<<"."<<endl;
50            cas--;
51     }
52     //system("pause");
53     return 0;
54 }

 

 

posted on 2010-03-11 20:02  白菜芯  阅读(433)  评论(0)    收藏  举报