USACO Training Section 2.1 Healthy Holsteins

英文原题 中文题译

大致题意:
    奶牛需要补充多种维生素,农夫手头有N种药丸,每种可以补充一定维生素,每个药丸每天只能吃一颗,问最少需要多少药丸,且要求输出药丸字典序最小的排列。

经典的0-1背包问题,当然可以非递归回溯,不过这里可以直接递归。需说明的是注意递归的顺序,先选择吃,再选择不吃。如果吃了就行,那么不吃就不用再算了,因为只需要输出字典序最小的,而不吃的情况下继续搜索一者药丸数必定不会减少,二者字典序上升,故可以剪枝。同时注意在这里剪枝时需恢复数据。

/*
ID: blackco3
TASK: holstein
LANG: C++
*/
#include <fstream>
#include <memory.h>

#define _max_vitamin_ 25
#define _max_feed_ 15
using namespace std;
int require[_max_vitamin_], feeds[_max_feed_][_max_vitamin_] ;
int n_vitamin, n_feed ;
int trace[_max_feed_], uses[_max_feed_], n_need=_max_feed_ ;

void get_need(int feed, int used)
{
	if( feed>=n_feed || used>=n_need )
		return ;
	int need_more=false ;
	for( int i=0; i<n_vitamin; i++ ){
		require[i] -= feeds[feed][i] ;
		if( require[i]>0 )
			need_more=true ;
	}
	uses[used++]=feed ;
	if( !need_more ){
		if( used<n_need ) {
			n_need=used ;
			memcpy( trace, uses, sizeof(int)*used );
		}
		for( int i=0; i<n_vitamin; i++ )
			require[i] += feeds[feed][i] ;
	} else {
		get_need( feed+1, used );
		for( int i=0; i<n_vitamin; i++ )
			require[i] += feeds[feed][i] ;
		get_need( feed+1, --used ) ;
	}
}

int main() {
    ofstream fout ("holstein.out");
    ifstream fin ("holstein.in");
	fin >> n_vitamin ;
	for( int i=0; i<n_vitamin; i++ )
		fin >> require[i] ;
	fin >> n_feed ;
	for( int i=0; i<n_feed; i++ )
		for( int j=0; j<n_vitamin; j++ )
			fin >> feeds[i][j] ;
	get_need(0,0);
	fout << n_need ;
	for( int i=0; i<n_need; i++ )
		fout << " " << trace[i]+1 ;
	fout << endl; 
	return 0;
} 

你可能感兴趣的:(C++,c,C#,J#,asp)