洛谷题解 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;
}
本文欢迎转载,转载时请注明本文链接