2101 - 枚举-练习-美食
c++刷题 超能力编程
唯一提示:简单dfs
还是提示一下吧:==对于每种食材都有取和不取两种情况,全都枚举并返回最终结果取最小值即可,注意题目要求不能一种食材都不要!!==这题方法很多
直接上代码:
f1:
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cmath>
#include <iostream>
using namespace std;
int n;
bool used[20];
struct S
{
int a = -1, b = -1;
}s[20];
int dfs(int pos)
{
if(s[pos].a != -1)
{
used[pos] = true;
int y = dfs(pos + 1);
used[pos] = false;
int n = dfs(pos + 1);
return min(y, n);
}else
{
bool bad = true;
int suan = 1;
int ku = 0;
for(int i = 0; i < n; i++)
if(used[i])
{
suan *= s[i].a;
ku += s[i].b;
bad = false;
}
if(bad)
return 1000000001;
else
return abs(suan - ku);
}
}
int main()
{
cin >> n;
for (int i = 0; i < n; i++)
cin >> s[i].a >> s[i].b;
s[n].a = -1;
printf("%d\n", dfs(0));
return 0;
}
f2:
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int M=15;//养成良好习惯
int a[M],b[M],n,ans=0x7fffffff;
//ans初始化为最大值
void dfs(int i,int x,int y){
//i是表示目前的配料编号,x为酸度,y为甜度
if(i>n){
//注意,必须大于n才表示全部搜完
if(x==1&&y==0)return;
//判断清水的情况
ans=min(abs(x-y),ans);
//更新ans
return;
}
//分两种情况搜索:1添加 2不添加
dfs(i+1,x*a[i],y+b[i]);
dfs(i+1,x,y);
//这题无需回溯,不明白为何有些题解居然还用全局变量,非得回溯-_-||
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d%d",&a[i],&b[i]);
//读入,用cin太慢了
}
dfs(1,1,0);
printf("%d\n",ans);
return 0;
}
f3:
#include <iostream>
#include <cmath>
using namespace std;
int n, s[15], b[15], ans=1e9;
void dfs(int k, int ss, int bb) {
if (k == n) {
if (ss == 1 && bb == 0)
return ;
ans = min(abs(ss - bb), ans);
return ;
}
dfs(k+1, ss*s[k], bb+b[k]);
dfs(k+1, ss, bb);
}
int main() {
cin >> n;
for (int i=0; i<n; ++i)
cin >> s[i] >> b[i];
dfs(0, 1, 0);
cout << ans << endl;
return 0;
}
f4:
#include<cstdio>
#include<algorithm>//头文件,min和abs在algorithm中(STL大法好)!
struct perket//定义结构体
{
int sour,sweet;//sour表示酸度,sweet表示甜度
}a[11];//配料
int s=1,w,ans=2147483646,n;//ans一开始开2147483647莫名RE,用2147483646就好了。。。。。。
long long ok;//ok表示所用配料数
inline void read(int &a)//这里详细解释一下快速读入,inline的作用为加快该函数所用时间,注意:若不止一个输入输出文件,则不可用inline!
{
char c;//定义字符存储变量
int k=1;a=0;//定义系数(初始为1)与所读入变量
c=getchar();//读入字符
while(c<'0'||c>'9'){if(c=='-')k=-1;c=getchar();}//如果该字符不为数字,跳过该字符,注意:由于本题有负数,所以要加判断是否为-号,如为-号,系数变为-1
while(c>='0'&&c<='9'){a=a*10+c-'0';c=getchar();}//如果该字符为数字,原数*10+该字符-‘0’,其实*10+是特别特别有用的一个东西,不在这里详细论述,以后有时间的话会专门发一篇文章来解释*10+与其作用
a*=k;//原数乘上系数
}
inline void print(int a)//快速输出
{
if(a>10)print(a/10);//如果当前该数超过10,输出除个位外部分
putchar(a%10+'0');//输出个位
}
void DFS(int i)//DFS,i表示当前搜索到第i个配料
{
if(i==n+1)return ;//如果全部搜索完毕,回溯
s*=a[i].sour;//当前酸度乘上该配料酸度
w+=a[i].sweet;//当前甜度加上该配料甜度
ok++;//所用配料数+1
ans=std::min(ans,abs(s-w));//更新答案,取原答案与甜酸度之差的最小值,有人说可以加一个特判:当ans=0时,直接输出!我没有这么做,因为个人感觉没啥用
DFS(i+1);//向下继续搜索
s/=a[i].sour;//当前酸度除以该配料酸度
w-=a[i].sweet;//当前甜度减去该配料甜度
ok--;//所用配料数-1
//这里解释一下:递归之前改变的值,递归过后一定要改回原值,即使你不再向下搜索,这也是递归的基本特征之一!!!
DFS(i+1);//向下继续搜索,这是为了保证答案的全面性
}
int main()
{
read(n);
for(int i=1;i<=n;i++){read(a[i].sour);read(a[i].sweet);}//输入,不解释
DFS(1);//DFS,从第一种配料开始搜索
print(ans);//输出答案
}