题意:农民JOHN以拥有世界上最健康的奶牛为傲。他知道每种饲料中所包含的牛所需的最低的维他命量是多少。请你帮助农夫喂养他的牛,以保持它们的健康,使喂给牛的饲料的种数最少。
给出牛所需的最低的维他命量,输出喂给牛需要哪些种类的饲料,且所需的饲料剂量最少。
维他命量以整数表示,每种饲料最多只能对牛使用一次,数据保证存在解。
思路:搜索每种饲料用了没有,即每层搜索有两种状态:vis[n]=0或vis[n]=1,且不必搜到n=G,只要搜到可供的维生素够用就可以退出(因为要求最少需要的饲料,再往后面走只会多不会少)
代码:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<utility>
#include<queue>
#include<iostream>
#include<algorithm>
const int maxn=30;
using namespace std;
int N;
int G;
int v[maxn]; //每种维生素所需
int jilu[maxn]; //记录搜索中所用过的饲料
int g[maxn][maxn]; //每种饲料能提供多少维生素
int vis[maxn]; //标记每种饲料用没有
int tg[maxn]; //已经提供了的维生素
int minn = 1000000;
void dfs(int n)
{
int flag = 1;
for(int i = 0; i < N; i++)
if(tg[i] < v[i])
{
flag = 0;
break;
}
if(flag)
{
int ans = 0;
for(int i =0 ; i < n; i++)
ans += vis[i];
if(ans <= minn)
{
minn = ans;
memset(jilu,0,sizeof(jilu));
for(int i = 0; i < G; i++)
if(vis[i] == 1) //绝不能写成vis[i],因为接下来所写的循环中vis[n]可能为2
jilu[i] = 1;
}
return ;
}
if(n == G) return ;
for(vis[n] = 0; vis[n] <= 1; vis[n]++)
{
for (int i = 0; i < N; i++)
tg[i] += g[n][i]*vis[n];
dfs(n+1);
for (int i = 0; i < N; i++)
tg[i] -= g[n][i]*vis[n];
}
}
int main()
{
freopen("holstein.in","r",stdin);
freopen("holstein.out","w",stdout);
memset(vis,0,sizeof(vis));
memset(tg,0,sizeof(tg));
cin>>N;
for(int i = 0; i < N; i++)
cin>>v[i];
cin>>G;
for(int i = 0; i < G; i++)
for(int j = 0; j < N; j++)
cin>>g[i][j];
dfs(0);
cout<<minn;
for(int i = 0; i < G; i++)
if(jilu[i])
cout<<' '<<i+1;
cout<<endl;
return 0;
}