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 }
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 for( int 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 }
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 for( int 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 }

浙公网安备 33010602011771号