题解一看就会,就是自己想不到orz
题意:n种食物,价格分别为pi,每天都会选择不同的搭配来吃,并且会尽量先选便宜的组合,问第K天的伙食需要花费多少钱
一开始队友的思路是01背包来判断一个值是否可解,然后从前往后扫到第K个可解的值即为答案。但是存在一个问题:我们不知道最大价格能达到多少,设置的比较大的话本地跑都比较久,自然就T了,虽然这道题没A出来,但是和队友讨论的过程中对背包加深了理解,比如队友解决了我01背包一维必须倒序的疑惑。
这道题的正确思路是子集枚举
对子集枚举还是掌握的不够好,这种方案完全就没想到,感觉有点像位向量法,每一种食物都有选和不选两种可能
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
typedef pair<long long,int> pli;
priority_queue<pli,vector<pli>,greater<pli> >q;
const int N=2e5+10;
int p[N];
int main()
{
int n,k;
cin>>n>>k;
for(int i=1;i<=n;++i)
cin>>p[i];
sort(p+1,p+1+n);
int cnt=0;
q.push(pli(p[1],1)); //pair->second代表的是当前方案中价格最贵的食物下标(考虑到的最后一个食物),first代表花费是多少
while(true)
{
pli tmp=q.top();
q.pop();
cnt++;
int idx=tmp.second;
int pri=tmp.first;
//cout<<pri<<' '<<idx;
if(cnt==k)
{
cout<<pri<<endl;
return 0;
}
if(idx<n) //注意要保证数组不越界
{
if(pri+p[idx+1])
q.push(pli(pri+p[idx+1],idx+1));
if(pri+p[idx+1]-p[idx])
q.push(pli(pri+p[idx+1]-p[idx],idx+1));
}
}
}
//#include<cstdio>
//#include<iostream>
//#include<cstring>
//#include<algorithm>
//#include<map>
//#include<vector>
//typedef long long ll;
//const int maxn = 2e5 + 10;
//using namespace std;
//map<ll, int> mp;
//vector<ll> vec;
//int p[maxn];
//int n, k;
//
//
//int main()
//{
// cin >> n >> k;
//
// int cnt = 0;
// mp[0] = 1;
// for(int i = 0; i < n; i++)
// scanf("%d", &p[i]);
// sort(p, p + n);
// bool flag = false;
// for(int i = 0; i < n; i++)
// {
// for(ll j = 1000000; j >= p[i]; j--)
// {
// cout<<i<<' '<<"?"<<endl;
//
// if(mp[j - p[i]])
// {
// cout<<"?"<<endl;
// mp[j]++;
// cnt++;
// cout << "cnt " << cnt << endl;
// vec.push_back(j);
//
// }
// }
// if(flag) break;
// }
// cout<<vec[k-1]<<endl;
// sort(vec.begin(), vec.end());
// cout << vec[k - 1] << endl;
// return 0;
//}