BJTU1935 铁憨憨骑士团的购买装备
题目:
在遥远的憨憨王国,有一个铁憨憨骑士团。
这天,憨帕斯正在参加骑士团第一届全团OGSC大赛。在当前的版本,OGSC一共有 𝑛
种装备可供购买,其中第 𝑖 种装备的价格是 𝑎𝑖
元。在一局游戏中 ,每一种装备最多只能被购买一次。注意,装备的价格有可能相同,但仍然视作不同的装备,可以被同时购买。
憨帕斯现在手中有 𝑚
块钱。现在,他想要知道,自己有多少种购买装备的方案,能够正好花光手里的 𝑚 块钱?
输入数据:
第一行两个整数 𝑛,𝑚 (1≤𝑛≤20,1≤𝑚≤1018) ,分别表示装备的种类数和憨帕斯手里的钱。
第二行一共 𝑛 个整数,其中第 𝑖 个整数 𝑎𝑖 (1≤𝑎𝑖≤1016) 表示第 𝑖 种装备的价格。
输出数据:
一个整数,表示正好花光 𝑚 块钱的方案数。
样例输入:
输入:
7 4750
4750 2700 1000 400 300 200 150
输出:
2
分析:
数据量不大20,并且要进行决策并判断,显然是深搜递归的思路,20个循环,所以一开始我就每一个循环写的从a[1]
到a[20]
的遍历,使用过的就vis[i] = true
。TLE…想想也是,20组数据的话,每一个循环20次运算,20个循环…
所以思考一下怎么优化,20个循环,我们把每次的循环修改为对于第i
个装备是否购买的决策,这样基数就是2了,最大O(2^20)。
代码:
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
bool vis[21];
int n;
long long m;
long long ans = 0;
long long a[21] = {0};
long long temp = 0;
void dfs(int now)
{
if(now == n + 1 || temp <= 0)
{
if(now == n + 1)
{
if(temp == 0)
{
ans++;
}
return;
}
if(temp == 0)
{
ans++;
return;
}
if(temp < 0)
{
return;
}
}
for(int i = 1;i >= 0;i--)
{
if(i)
{
temp -= a[now];
dfs(now + 1);
temp += a[now];
}
else
{
dfs(now + 1);
}
}
}
int main()
{
cin>>n>>m;
for(int i = 1;i <= n;i++)
{
cin>>a[i];
}
temp = m;
memset(vis,false,sizeof(vis));
dfs(1);
cout<<ans<<endl;
return 0;
}