洛谷题解 P1460 [USACO2.1]健康的荷斯坦奶牛 Healthy Holsteins

原题传送门

0.前言 码了好长时间啊......
1.思路
很显然,是一道搜索(与回溯)的暴力题,思路也很简单:

  • 在合法(奶牛不是营养不良)的情况下若当前的情况选出的维他命比原来的结果小,就更新
  • 选当前饲料,就搜索一步
  • 不选当前饲料,就回溯

代码到这里也很显然了

2.代码

#include<iostream>
#include<cstdio>
using namespace std;
inline void read(int &x){	//快读 
	int f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-') f=-1;
		ch=getchar();
 	}
 	while(ch>='0'&&ch<='9'){
 		x=x*10+ch-'0';
 		ch=getchar();
	}
	x*=f; 
}
int n;	//输入的维他命的种类数 
int kind;	//输入的可以喂奶牛的饲料种数 
int res[1001];	//存储解的数组 
int minx[1001];	//每种维他命需要的最小量
int sum[1001][1001]; //每种饲料包含维他命的量 
int num[1001];	//选的维他命编号 
int minn=1001;	//最小需要用的饲料数量 
inline bool judge(int p){	//判断当前饲料数是否合法( 
	for(int i=1;i<=n;i++){
		int summ=0;
		for(int j=1;j<=p;j++) summ+=sum[num[j]][i];	//计算当前选的饲料里的维他命的总量 
		if(summ<minx[i]) return false;
	}
	return true;
}
inline void search(int f,int cnt){	//搜索
	//f表示当前搜到第f种饲料,cnt表示当前一共选了cnt种饲料 
	if(f>kind){	//边界条件,如果当前的种数比能选的种数多 
		if(judge(cnt)){	//合法的情况下 
			if(cnt<minn){	//如果当前的方案比已知的最优解好 
				minn=cnt;	//替换种数 
				for(int i=1;i<=minn;i++){
					res[i]=num[i];	//替换选的编号 
				}
			}
		}
		return;
	}
	num[cnt+1]=f;	 //选,存入数组 
	search(f+1,cnt+1);//搜索一步 
	num[cnt+1]=0;	//不选,不存 
	search(f+1,cnt);	//回溯一步(f需+1,表示到了下一种饲料) 
}
int main(){
	read(n);
	for(int i=1;i<=n;i++) read(minx[i]);
	read(kind);
	for(int i=1;i<=kind;i++){
		for(int j=1;j<=n;j++){
			read(sum[i][j]);
		}
	}
	search(1,0);	//第一种,当前选了0种 
	printf("%d ",minn);
	for(int i=1;i<=minn;i++) printf("%d ",res[i]);
	return 0;
}
posted @ 2020-09-18 17:16  _pwl  阅读(425)  评论(1编辑  收藏  举报
1 2 3
4