这题拖了很久,一开始想用dfs结果写不出来,然后在网上看到应该枚举而且又看到这种状态压缩枚举算学到东西了,接着又看到用bfs的。
/*
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;
}
第二种方法就是简单的bfs不过他记录路径的方法很巧妙,学习了。代码直接搬过来了
/*
ID :jinbo wu
LANG: C++
TASK:holstein
*/
#include<bits/stdc++.h>
using namespace std;
int a[30];
int b[20][30];
int ans[25];
int t[25];
int sum,mark,flag,cnt;
int main()
{
freopen("holstein.in","r",stdin);
freopen("holstein.out","w",stdout);
int n,l;
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
int g;
scanf("%d",&g);
for(int i=0;i<g;i++)
{
for(int j=0;j<n;j++)
scanf("%d",&b[i][j]);
}
int maxn=1<<g;
sum=maxn;
for(int i=1;i<=maxn;i++)
{
flag=0;
cnt=0;
int temp=i;
while(temp)
{
if(temp&1) cnt++;
if(cnt>=sum)
{
flag=1;
break;
}
temp>>=1;
}
if(flag)
continue;
temp=i;
l=0;
memset(t,0,sizeof(t));
while(temp)
{
if(temp&1)
{
for(int j=0;j<n;j++)
t[j]+=b[l][j];
}
temp>>=1;
l++;
}
for(int j=0;j<n;j++)
{
if(t[j]<a[j])
{
flag=1;
break;
}
}
if(flag==0)
{
sum=cnt;
mark=i;
}
}
printf("%d",sum);
l=1;
while(mark)
{
if(mark&1)
printf(" %d",l);
mark>>=1;
l++;
}
printf("\n");
}
第二种方法就是简单的bfs不过他记录路径的方法很巧妙,学习了。代码直接搬过来了
第二种方法就是简单的bfs不过他记录路径的方法很巧妙,学习了。代码直接搬过来了