USACO 2.14 Healthy Holsteins(BFS)

题意:农民JOHN以拥有世界上最健康的奶牛为傲。他知道每种饲料中所包含的牛所需的最低的维他命量是多少。请你帮助农夫喂养他的牛,以保持它们的健康,使喂给牛的饲料的种数最少。

给出牛所需的最低的维他命量,输出喂给牛需要哪些种类的饲料,且所需的饲料剂量最少。

维他命量以整数表示,每种饲料最多只能对牛使用一次,数据保证存在解。

输出:

输出文件只有一行,包括

牛必需的最小的饲料种数P

后面有P个数,表示所选择的饲料编号(按从小到大排列)。

如果有多个解,输出饲料序号最小的(即字典序最小)。

分析:总共有十五种饲料,要找出符合能满足条件的最少的种数,相当于要求出一种组合,那么就求出各种长度的组合,再找出符合条件的最小字典序。

用BFS做的,关键是记录状态,每一个状态要记录几个量

struct node
{
 int state;//用位来记录路径,即使用过哪几种饲料
 int ver[26];//保存状态值,
 short cur;//当前选择的编号最大的饲料
 short cnt;//已选择的种类数
};

每次取出一种状态时,从当前最大饲料的编号之后开始添加选择的饲料,同时记录下所选择的饲料编号,这样,第一个满足条件就题目所求的。

以 测试例子为例:

整个搜索过程是这样的:

先将这三个状态压入对列 (1)  (2)  (3)

 取出(1)之后,就会分别将(1, 2)  (1,3)

取出(2)  之后,就会将(2,3)

取出(3) 之后……

 取出(1,2)之后,就会将(1,2,3)

取出(1,3)之后,满足条件,退出;

之后输出就比较简单了;

/*
ID: nanke691
LANG: C++
TASK: holstein
*/
#include<iostream>
#include<fstream>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
struct node
{
	int state;//用位来记录路径,即使用过哪几种饲料
	int ver[26];//保存状态值,
	short cur;//当前选择的编号最大的饲料
	short cnt;//已选择的种类数
};
int hol[20][30];
int V,G,aim[30],len,ans;
queue<node> Q;
bool  compare(int *a)//判断是否符合条件
{
	for(int i=1;i<=V;i++)
		if(a[i]<aim[i])
			return false;
	return true;
}
void BFS()
{
	node s,f;
	for(int i=1;i<=G;i++)
	{
		for(int j=1;j<=V;j++)
			s.ver[j]=hol[i][j];
		s.state=(1<<(i-1));
		s.cur=i;
		s.cnt=1;
		Q.push(s);
	}
	len=100000000;
	while(!Q.empty())
	{
		f=Q.front();
		Q.pop();
		if(f.cnt<=len && compare(f.ver))
		{

			len=f.cnt;	
			ans=f.state;
			break;
		}
		for(int i=f.cur+1;i<=G;i++)
		{
			for(int j=1;j<=V;j++)
				s.ver[j]=f.ver[j]+hol[i][j];
			s.cnt=f.cnt+1;
			s.cur=i;
			s.state=(f.state | (1<<(i-1)));//记录下当前选取的编号
			Q.push(s);
		}
	}
}
int main()
{
	freopen("holstein.in","r",stdin);
	freopen("holstein.out","w",stdout);
	scanf("%d",&V);
	for(int i=1;i<=V;i++)
		scanf("%d",&aim[i]);
	scanf("%d",&G);
	for(int i=1;i<=G;i++)
		for(int j=1;j<=V;j++)
			scanf("%d",&hol[i][j]);
	BFS();
	cout<<len<<' ';
	int flag=0;
	for(int i=1;i<=G;i++)
	{
		if((ans &(1<<(i-1)))!=0)
		{
			if(!flag)
			cout<<i,flag=1;
			else cout<<' '<<i;
		}
	}
	cout<<endl;
}

 

posted @ 2011-10-26 18:46  枕边梦  阅读(681)  评论(0编辑  收藏  举报