[浅谈] 邻项交换排序贪心

参考文献

浅谈邻项交换排序的应用以及需要注意的问题

总结

对于一些决定贪心顺序的题目,我们可以通过确定相邻两个人的排列关系来确定最优顺序。但是相邻最优推广到全局最优还需要证明两种关系:

  1. 可比传递性。 当 ai<ajaj<ak 时,还应当保证 ai<ak

  2. 不可比传递性,如果 ai=ajaj=ak ,还应当保证 ai<=ak

例题

P1080 [NOIP2012 提高组] 国王游戏

考虑相邻的人 P1P2 ,设他们左右手分别为 aibi ,设他们前面的人左手乘积为 t

如果 P1 在前, ans=max(tb1,ta1b2)
P2 在前同理, ans=max(tb2,ta2b1)

其实已经可以做了。但是这个式子仍能化简。ta2b1>tb1ta1b2>tb2 ,所以可以变成比较 ta2b1ta1b2

最后,我讨厌高精度。

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5010;
int read(){
	int x=0,f=1;char c=getchar();
	while(c>'9' || c<'0'){if(c=='-')f=-1;c=getchar();}
	while(c>='0' && c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return x*f;
}
struct node{
	int a,b;
}e[N];
bool cmp(node t1,node t2){
	return t2.a*t2.b>t1.a*t1.b;
}
int n,A[N],B[N];
struct NUM{
	int len,num[10000010];	
}S1,S2,S3;
void add(int x){
	for(int i=1;i<=S1.len;i++)S1.num[i]*=x;
	for(int i=1;i<S1.len;i++){
		S1.num[i+1]+=S1.num[i]/10;
		S1.num[i]%=10;
	}
	while(S1.num[S1.len]>=10){
		S1.num[S1.len+1]+=S1.num[S1.len]/10;
		S1.num[S1.len]%=10;
		S1.len++;
	}
	return;
}
void del(int x){
	int tmp=0;
	S2.len=0;
	for(int i=S1.len;i>=1;i--){
		tmp=tmp*10+S1.num[i];
		if(tmp>=x){
			S2.len=max(S2.len,i);
			S2.num[i]=tmp/x;
			tmp%=x; 
		}
		else S2.num[i]=0; 
	}
	return;
}
bool gt(){
	if(S2.len!=S3.len)return S2.len>S3.len;
	for(int i=S2.len;i>=1;i--)
		if(S2.num[i]!=S3.num[i])
			return S2.num[i]>S3.num[i];
}
void rp(){
	S3.len=S2.len;
	for(int i=S3.len;i>=1;i--)
		S3.num[i]=S2.num[i];
	return;
}
signed main(){
	n=read();
	e[0].a=read(),e[0].b=read();
	for(int i=1;i<=n;i++)e[i].a=read(),e[i].b=read();
	sort(e+1,e+n+1,cmp);
	
	S1.len=1;S1.num[1]=1;
	for(int i=1;i<=n;i++){
		add(e[i-1].a);
		del(e[i].b);
		if(gt())rp();
	}
	for(int i=S3.len;i>=1;i--)
		printf("%lld",S3.num[i]);
	printf("\n");
	S1.len=1;S1.num[1]=1;
	return 0;
}

P1248 加工生产调度

本做法仅供参考,正确性无法保证。

那两个物品,编号为 12
1 在前: ans=a1+max(a2,b1)+b2
2 在前: ans=a2+max(a1,b2)+b1

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int read(){
	int x=0,f=1;char c=getchar();
	while(c>'9' || c<'0'){if(c=='-')f=-1;c=getchar();}
	while(c>='0' && c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return x*f;
}
struct node{
	int a,b,id;
}e[N];
bool cmp(node t1,node t2){
	return min(t1.a,t2.b)<min(t2.a,t1.b);
}
int n,A[N],B[N];
int main(){
	n=read();
	for(int i=1;i<=n;i++)e[i].a=read();
	for(int i=1;i<=n;i++)e[i].b=read(),e[i].id=i;
	sort(e+1,e+n+1,cmp);
	for(int i=1;i<=n;i++){
		A[i]=A[i-1]+e[i].a;
		B[i]=max(B[i-1],A[i])+e[i].b;
	}
	printf("%d\n",B[n]);
	for(int i=1;i<=n;i++)
		printf("%d ",e[i].id);
	printf("\n");
	return 0;
}
posted @   FJOI  阅读(45)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示