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;
}

浙公网安备 33010602011771号