题目描述 Description
农民JOHN以拥有世界上最健康的奶牛为傲。他知道每种饲料中所包含的牛所需的最低的维他命量是多少。请你帮助农夫喂养他的牛,以保持它们的健康,使喂给牛的饲料的种数最少。
给出牛所需的最低的维他命量,输出喂给牛需要哪些种类的饲料,且所需的饲料剂量最少。
维他命量以整数表示,每种饲料最多只能对牛使用一次,数据保证存在解。
输入描述 Input Description
第1行:一个整数V(1<=V<=25),表示需要的维他命的种类数。
第2行:V个整数(1<=每个数<=1000),表示牛每天需要的每种维他命的最小量。
第3行:一个整数G(1<=G<=15),表示可用来喂牛的饲料的种数。
下面G行,第n行表示编号为n饲料包含的各种维他命的量的多少。
输出描述 Output Description
输出文件只有一行,包括
牛必需的最小的饲料种数P
后面有P个数,表示所选择的饲料编号(按从小到大排列)。
如果有多个解,输出饲料序号最小的(即字典序最小)。
题解
智商君连续下线,苦逼翻译这么久原来codevs上有中文得 (其实也不是第一次知道了)
专题就是暴力搜索啊,dfs,枚举当前状态选不选。n很小就要想到状压了,用二进制记录一下。
优化?
记录一个当前的最小答案长度,如果搜到当前状态已经不可能最优就退咯,为了避免相同长度的不同答案,长度相同的以先出现为优先
code
/*
ID:wjp13241
PROG:holstein
LANG:C++
*/
#include <stdio.h>
using namespace std;
struct feeds
{
int a[31];
feeds operator+(feeds &b)
{
feeds sum={0};
for (int i=1;i<=30;i++) sum.a[i]=a[i]+b.a[i];
return sum;
}
};
int ans[31],v[31];
int n,m,f,min;
feeds t[31];
int check(feeds x)
{
for (int i=1;i<=m;i++)
if (x.a[i]<v[i])
return 0;
return 1;
}
void print(int count,int state)
{
ans[0]=0;
int i=0;
while (state&&i<n)
{
i++;
if (state%2)
ans[++ans[0]]=i;
state/=2;
}
min=count;
}
void dfs(int dep,feeds now,int count,int state)
{
if (check(now)&&count<min)
{
print(count,state);
return;
}
if (dep>n||count>=min)
return;
dfs(dep+1,now+t[dep],count+1,state+(1<<(dep-1)));
dfs(dep+1,now,count,state);
}
int main()
{
freopen("holstein.in","r",stdin);
freopen("holstein.out","w",stdout);
scanf("%d",&m);
for (int i=1;i<=m;i++)
scanf("%d",&v[i]);
scanf("%d",&n);
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
scanf("%d",&t[i].a[j]);
min=n+1;
dfs(1,(feeds){{0}},0,0);
printf("%d",ans[0]);
for (int i=1;i<=ans[0];i++)
printf(" %d",ans[i]);
printf("\n");
fclose(stdin);
fclose(stdout);
return 0;
}