洛谷之PERKET
洛谷P2036 [COCI2008-2009#2] PERKET
https://www.luogu.com.cn/problem/P2036
先分析题目,题目中有n种食材,每食材有酸度和苦度,然后要求选取食材,使酸度和苦度绝对值差最小,其中酸度是相乘,苦度是相加。
很明显 ,题目的意思是要我们算出所有绝对值差,然后找出里面最小的,既然是求最小值,我第一反应想到的就是C++里algorithm里的min函数,可以直接帮我们计算两个值中的最小值,既然是算出所有绝对值差,那么肯定是用搜索啦!
下面放代码:
#include <iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
#define MAXN 0x3f3f3f;
struct MS
{
int x;
int y;
}T[100000];//首先定义结构体
int s = 1, k = 0;
int n;
int sum = 0x3f3f3f3f;
bool vis[100000];//判断是否走过
void dfs(int start, int total)//深搜,start表示开始搜的点,total表示酸度和苦度的和
{
sum = min(total, sum);//c++中min函数 需要头文件algorithm。
if (start > n)//如果start>n,即搜索的点比食材数目大,返回上一步
return;
for (int i = 1; i <= n; i++)
{
if (!vis[i])//如果点不为空
{
s *= T[i].x;/酸度相乘
k += T[i].y;//苦度相加
vis[i] = 1;//标记点已经走过
total = abs(s - k);//总和等于酸度减去苦度的绝对值 abs表示计算绝对值,在math头文件中
dfs(i + 1, total);//搜索下一个食材。
s /= T[i].x;//这里是回溯 就是从1开始搜到底之后,回溯到之前初始状态,从2搜到底,以此类推。
k -= T[i].y;
vis[i] = 0;
}
}
}
int main()
{
cin >> n;
memset(vis, 0, sizeof(vis));
for (int i = 1; i <= n; i++)
{
cin >> T[i].x >> T[i].y;
}
dfs(1, 100000);
cout << sum;
}