P4531[CTSC2005]魔术眼镜盒

考虑两个比较好想贪心。

$ 1. $ 既然要数量最大,优先从小选的比较优 。

$ 2. $ 两个比较大小接近的放在一起比较优 。

现将原数组排序。

手玩几组样例发现,为了满足贪心原则 $ 1 , 2 $ ,最后的答案肯定是从 $ 1 $ 开始的连续一段。

可以考虑枚举连续一段的端点,判定是否合法即可。

复杂度 $ O(n^2) $ ,实际远远达不到。

#include<bits/stdc++.h>
#define int long long
using namespace std;
inline int rd(){
	int x=0,f=1;char ch=getchar();
	while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
	while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
vector<int> s1,s2;
int Ans_cnt,Now_s;
int n,m,s,num;

signed main()
{
//	   s1.resize(55000);
//	   s2.resize(55000);
//	   freopen("7.in","r",stdin);
//	   freopen("Ans.out","w",stdout);
	   n=rd();
	   m=rd();
	   s=rd();
	   for(int i=1;i<=n;i++)
	   {
	       int a;
	       a=rd();
	   	   s1.push_back(a);
	   }
	   for(int i=1;i<=m;i++)
	   {
           int a;
	   	   a=rd();
	   	   s2.push_back(a);
	   }
       if(s1.size()<s2.size()) s1.swap(s2);
	   sort(s1.begin(),s1.end());
	   sort(s2.begin(),s2.end());
	   int sum=0;
	   for(vector<int>::iterator it=s1.begin();it!=s1.end();it++)
       {
       	   int cnt=num;
       	   int Maxn=0,xuan;
		   if(it==s1.end()) continue;
		   vector<int>::iterator it1=it;
       	   vector<int>::iterator it2=s2.begin();
       	   int now_sum=sum;
       	   while(1)
       	   {
       	   	     Maxn=max(*it1,*it2);
       	         if((now_sum+Maxn)*Maxn>s) break;
       	         xuan=Maxn;
       	         now_sum+=Maxn;
				 cnt+=2;
				 it1++;
				 it2++;
				 if(it1==s1.end()||it2==s2.end()) break;
		   }
	   	   if(cnt>Ans_cnt)
		   {
		   	  Now_s=xuan*now_sum;
		   	  Ans_cnt=cnt;
		   }
           else	if(cnt==Ans_cnt)
		   {
		   	  Now_s=min(Now_s,xuan*now_sum);
		   }
		   sum+=*it;
		   num++;
		   if(sum*Maxn>s||it1==s1.end()) break;
	   }
	   cout<<Ans_cnt<<" "<<Now_s<<endl;
} 
posted @ 2022-04-02 19:06  Authentic_k  阅读(50)  评论(0编辑  收藏  举报