E - Kth Takoyaki Set

发布时间 2023-04-15 09:54:37作者: 铃狐sama

E - Kth Takoyaki Set

题目来源:E - Kth Takoyaki Set (atcoder.jp)

题目大致意思:

给你几个数,把他们各种排列的和(每个数字可以多次使用,不一定每个数字都要选)的第k小的ans是多少

思路:

第一想法是背包吧,但是很明显这个作为val的范围第一很大,第二无法确定正确的范围,总之很难写

于是我就想了第二种方法,假设当前可能有n种答案作为当前答案,其中最小的为k,那么下一个答案肯定是已有答案中加上当前最小值k

于是就有了广搜的超时代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
vector<long long>s;//我的第1想法是背包,放弃了,第二想法是广搜
priority_queue<int,vector<int>, greater<int> >q;
signed main(){
	ios::sync_with_stdio(false);
	int n,k;
	cin >> n >> k;
	for(int i=1;i<=n;i++){
		long long p;
		cin >> p;
		q.push(p);
	}
	while(!q.empty()&&s.size()<k){
		int v=q.top();
		q.pop();
		if(s.size()!=0&&v==s[s.size()-1]){
			continue;
		}
		s.push_back(v);
		if(s.size()==k){
			break;
		}
		for(int i=0;i<s.size();i++){
			if(s.size()>=k){
				break;
			}
			q.push(v+s[i]);
		}
	}
	cout<<s[k-1];
	
}

这个代码很容易理解,那么剪肢时间就来了

#include<bits/stdc++.h>
#define int long long
using namespace std;
vector<long long>s;//我的第1想法是背包,放弃了,第二想法是广搜
priority_queue<int,vector<int>, greater<int> >q;
long long val[15];
signed main(){
	ios::sync_with_stdio(false);
	int n,k;
	cin >> n >> k;
	for(int i=1;i<=n;i++){
		long long p;
		cin >> p;
		q.push(p);
		val[i]=p;
	}
	while(!q.empty()&&s.size()<k){
		int v=q.top();
		q.pop();
		if(s.size()!=0&&v==s[s.size()-1]){
			continue;
		}
		s.push_back(v);
		if(s.size()==k){
			break;
		}
//		for(int i=0;i<n;i++){//这里有问题,因为前几个不一定就是1-n 
////			q.push(v+s[i]);
//		}
		//改为 
		for(int i=1;i<=n;i++){
			q.push(v+val[i]);
		}
	}
	cout<<s[k-1];
	
}

思路就是,将原来最小值k加所有已经有的答案作为下一次答案改为了将最小值k加最先给你的那10个数作为下一次答案

为什么,可以想到,在所有已有的答案中,必然有一些是有重复选择的,比如说答案n可能是由a1+a1+a2组成的,而这个肯定比a1、a2大,我们只需要判断a1即可,由此剪了很多很多的时间复杂度