[usaco]5.3.2 Milk Measuring 动态规划

 
Milk Measuring
Hal Burch
Farmer John must measure Q (1 <= Q <= 20,000) quarts of his finest milk and deliver it in one big bottle to a customer. He fills that bottle with exactly the number of quarts that the customer orders.

Farmer John has always been frugal. He is at the cow hardware store where he must purchase a set of pails with which to measure out Q quarts of milk from his giant milk tank. Since the pails each cost the same amount, your task is to figure out a minimal
set of pails Farmer John can purchase in order to fill a bottle with exactly Q quarts of milk. Additionally, since Farmer John has to carry the pails home, given two minimal sets of pails he should choose the “smaller” one as follows: Sort the sets in ascending
order. Compare the first pail in each set and choose the set with the smallest pail. If the first pails match, compare the second pails and choose from among those, else continue until the two sets differ. Thus the set {3, 5, 7, 100} should be chosen over
{3, 6, 7, 8}.

To measure out milk, FJ may completely fill a pail from the tank and pour it into the bottle. He can never remove milk from the bottle or pour milk anywhere except into the bottle. With a one-quart pail, FJ would need only one pail to create any number of
quarts in a bottle. Other pail combinations are not so convenient.

Determine the optimally small number of pails to purchase, given the guarantee that at least one solution is possible for all contest input data.

PROGRAM NAME: milk4
INPUT FORMAT
Line 1: The single integer Q 
Line 2: A single integer P (1 <= P <= 100) which is the number of pails in the store 

Lines 3..P+2: Each line contains a single integer pail_value (1 <= pail_value <= 10000), the number of quarts a pail holds 

SAMPLE INPUT (file milk4.in)
16
3
3
5
7

OUTPUT FORMAT
The output is a single line of space separated integers that contains:

the minimum number of pails required to measure out the desired number of quarts, followed by:

a sorted list (from smallest to largest) of the capacity of each of the required pails

SAMPLE OUTPUT (file milk4.out)
2 3 5

 

——————————————————————————–
典型的动态规划,但是这里有两个条件:桶最少;相同数目的桶,取比较小的那些。
不过,当这两个条件相互冲突时,应该如何取舍?
使用动态规划的基本思路是:
如果能够满足q量的牛奶,那么这q+任一个桶的量所得的数目也一定能够满足。

   Test 1: TEST OK [0.000 secs, 5080 KB]
   Test 2: TEST OK [0.000 secs, 5080 KB]
   Test 3: TEST OK [0.000 secs, 5080 KB]
   Test 4: TEST OK [0.000 secs, 5080 KB]
   Test 5: TEST OK [0.000 secs, 5080 KB]
   Test 6: TEST OK [0.000 secs, 5080 KB]
   Test 7: TEST OK [0.027 secs, 5080 KB]
   Test 8: TEST OK [0.135 secs, 5080 KB]
   Test 9: TEST OK [0.054 secs, 5080 KB]
   Test 10: TEST OK [0.135 secs, 5080 KB]
我在网上找这个的测试用例的时候,没法先哪个人上传过的,因此特地把测试用例作为附件上传。

/*
ID:yunleis3
PROG:milk4
LANG:C++
*/


#include <fstream>
#include<iostream>

using namespace std;
const int maxq=20001;
const int maxp=101;
bool metri[maxq][maxp];
int pailnum[maxq];
int q,p;
//#define  DEBUG
int pail[maxp];
 
void quicksort(int * a,int p,int r);
int middleq;
int main()
{
	ifstream fin("milk4.in");
	fin>>q>>p;
	for(int i=0;i<p;++i){
		fin>>pail[i];
		metri[pail[i]][i]=true;
		pailnum[pail[i]]=1;
	}
	//quicksort(pail,0,p-1);
	 solve1();
 
	int *result1=new int[pailnum[q]];
	int ptr1=0;
	for(int i=0;i<p;++i){
		if(metri[q][i])
			result1[ptr1++]=pail[i]; 
	}
	quicksort(result1,0,ptr1-1);
	for(int i=0;i<q;++i){
		for(int j=0;j<p;++j)
			metri[i][j]=false;
		pailnum[i]=0;	
	}
	for(int i=0;i<p;++i){ 
		metri[pail[i]][i]=true;
		pailnum[pail[i]]=1;
	}
	 nochange=true;
	for(int i=1;i<=q&&nochange;++i){
		nochange=false;
		for(int j=0;j<p;++j){
			if(i+pail[j]>q)
				continue;
			nochange=true; 
			int num=metri[i][j]?0:1;
			bool flag=false;
			if(pailnum[i]==0)
				flag=false;
		//	else if(pailnum[i+pail[j]]==0||(num+pailnum[i])<pailnum[i+pail[j]]){
			//	flag=true;
			//}
			else {
				bool metritmp=metri[i][j];
				metri[i][j]=true;
				for(int ss=0;ss<=p;++ss){
					if(metri[i][ss]&&!metri[i+pail[j]][ss]){
						flag=true;
						break;
					}
					else if(!metri[i][ss]&&metri[i+pail[j]][ss])
						break;
				}
				metri[i][j]=metritmp;
			}
			if(flag){
				for(int ss=0;ss<p;++ss){					 
					metri[i+pail[j]][ss]=metri[i][ss];					 
				}
				metri[i+pail[j]][j]=true;
				pailnum[i+pail[j]]=(num+pailnum[i]);
 
			}
		}
	}
	ofstream fout("milk4.out");
	

	 
	int *result=new int[pailnum[q]];
	int ptr=0;
	for(int i=0;i<p;++i){
		if(metri[q][i])
			result[ptr++]=pail[i];//fout<<" "<<pail[i];
	}
	p=ptr;	
	for(int i=0;i<q;++i){
		for(int j=0;j<p;++j)
			metri[i][j]=false;
		pailnum[i]=0;	
	}
	for(int i=0;i<p;++i){
		pail[i]=result[i];
		metri[pail[i]][i]=true;
		pailnum[pail[i]]=1;
	}
	solve1();
	
	ptr=0;
	for(int i=0;i<p;++i){
		if(metri[q][i])
			result[ptr++]=pail[i];//fout<<" "<<pail[i];
	}
	if(ptr1<ptr)
	{
		int * resulttmp=result1;
		result1=result;
		result=resulttmp;
		ptr=ptr1;
	}
	else if(ptr1==ptr){

	}
 	fout<<ptr;
	quicksort(result,0,ptr-1);
	for(int i=0;i<ptr;++i)		 
		fout<<" "<<result[i];
	fout<<endl;
	delete [] result;
	delete [] result1;
	//system("pause");
}
 void solve1()
 {
	bool  nochange=true;
	 for(int i=1;i<=q&&nochange;++i){
		 nochange=false;
		 for(int j=0;j<p;++j){
			 if(i+pail[j]>q)
				 continue;
			 nochange=true; 
			 int num=metri[i][j]?0:1;
			 bool flag=false;
			 if(pailnum[i]==0)
				 flag=false;
			 else if(pailnum[i+pail[j]]==0||(num+pailnum[i])<pailnum[i+pail[j]]){
				 flag=true;
			 }
			 else if((num+pailnum[i])==pailnum[i+pail[j]]){
				 bool metritmp=metri[i][j];
				 metri[i][j]=true;
				 for(int ss=0;ss<=p;++ss){
					 if(metri[i][ss]&&!metri[i+pail[j]][ss]){
						 flag=true;
						 break;
					 }
					 else if(!metri[i][ss]&&metri[i+pail[j]][ss])
						 break;
				 }
				 metri[i][j]=metritmp;
			 }
			 if(flag){
				 for(int ss=0;ss<p;++ss){					 
					 metri[i+pail[j]][ss]=metri[i][ss];					 
				 }
				 metri[i+pail[j]][j]=true;
				 pailnum[i+pail[j]]=(num+pailnum[i]);

			 }
		 }
	 }

 }
void swap(int * a,int * b){
	int t=*a;
	*a=*b;
	*b=t;
}
int partion(int * a,int p,int r){
	int x=a[r];
	int i=p-1;
	for(int j=p;j<r;++j){
		if(a[j]<x){
			i++;
			swap(a+i,a+j);
		}
	}
	i++;
	swap(a+r,a+i);
	return i;
}
void quicksort(int * a,int p,int r){
	if(p<r){
		int q=partion(a,p,r);
		quicksort(a,p,q-1);
		quicksort(a,q+1,r);
	}
}

————————————–

Here are the test data inputs:

——- test 1 —-
16
3
3
5
7
——- test 2 —-
20
3
1
2
4
——- test 3 —-
59
3
7
11
13
——- test 4 —-
8722
2
89
97
——- test 5 —-
323
5
97
101
103
107
119
——- test 6 —-
20000
3
233
151
413
——- test 7 —-
5334
100
1009
1013
1019
1021
1031
1033
1039
1049
1051
1061
1063
1069
1087
1091
1093
1097
1103
1109
1117
1123
1129
1151
1153
1163
1171
1181
1187
1193
1201
1213
1217
1223
1229
1231
1237
1249
1259
1277
1279
1283
1289
1291
1297
1301
1303
1307
1319
1321
1327
1361
1367
1373
1381
1399
1409
1423
1427
1429
1433
1439
1447
1451
1453
1459
1471
1481
1483
1487
1489
1493
1499
1511
1523
1531
1543
1549
1553
1559
1567
1571
1579
1583
1597
1601
1607
1609
1613
1619
1621
1627
1637
1657
1663
1667
1669
1693
1697
1699
1709
1721
——- test 8 —-
15383
100
997
998
1000
1003
1007
1012
1018
1025
1033
1042
1052
1063
1075
1088
1102
1117
1133
1150
1168
1187
1207
1228
1250
1273
1297
1322
1348
1375
1403
1432
1462
1493
1525
1558
1592
1627
1663
1700
1738
1777
1817
1858
1900
1943
1987
2032
2078
2125
2173
2222
2272
2323
2375
2428
2482
2537
2593
2650
2708
2767
2827
2888
2950
3013
3077
3142
3208
3275
3343
3412
3482
3553
3625
3698
3772
3847
3923
4000
4078
4157
4237
4318
4400
4483
4567
4652
4738
4825
4913
5002
5092
5183
5275
5368
5462
5557
5653
5750
5848
5947
——- test 9 —-
19829
20
708
727
764
825
916
1043
1212
1429
1700
2031
2428
2897
3444
4075
4796
5613
6532
7559
8700
9961
——- test 10 —-
16737
94
904
909
916
925
936
949
964
981
1000
1021
1044
1069
1096
1125
1156
1189
1224
1261
1300
1341
1384
1429
1476
1525
1576
1629
1684
1741
1800
1861
1924
1989
2056
2125
2196
2269
2344
2421
2500
2581
2664
2749
2836
2925
3016
3109
3204
3301
3400
3501
3604
3709
3816
3925
4036
4149
4264
4381
4500
4621
4744
4869
4996
5125
5256
5389
5524
5661
5800
5941
6084
6229
6376
6525
6676
6829
6984
7141
7300
7461
7624
7789
7956
8125
8296
8469
8644
8821
9000
9181
9364
9549
9736
9925