【学习笔记】[BalticOI 2007 Day 1] Ranklist Sorting

论文题(挺考验语文阅读能力的,足足花了我一晚上+一下午)

论文出处

首先感性地得到两个推论(这是我们后续按顺序 dp 的基础):

  1. 最有决策中一定是从大往小操作
  2. 对于数 x 来说,要么在原地不动,要么移动到 x+1 的前一个位置

现在我们修改一下这个操作的定义:

在这里插入图片描述
我们不改变没有操作的点的位置,而是 并列放置 。这样的放置对后面 dp 转移方程的推导很有帮助。

我们可以令 f [ x ] [ p 2 ] f[x][p2] f[x][p2] 表示把 x x x 移动到原序列的 p 2 p2 p2 位置且 x + 1 x+1 x+1 n n n 都在 p 2 p2 p2 的最小费用。 p o s [ x ] pos[x] pos[x] 表示 x x x 在原序列中位置。

先来考虑 p o s [ x ] < p 2 pos[x]<p2 pos[x]<p2 即往后移动的情况。

我们定义 c ( p , x ) c(p,x) c(p,x) 表示 1 到 p 中小于 x 的位置的个数 + 1。那么 x 的真实位置其实就是 c ( p , x ) c(p,x) c(p,x)

有方程 f[x][p2]=f[x+1][p2]+c(p,x)+c(p2,x) (之所以 -1 是因为要移动到 x+1 的前一位)

那么 p o s [ x ] > p 2 pos[x]>p2 pos[x]>p2 呢?

在这里插入图片描述
显然可以归到上一种情况,即 f[x][p2]=f[x+1][p2]+c(p,x)+c(p2,x)+(4-3) (注意这里 (4-3) 其实是提前计算的,后面会讲)

下面我们考虑如何计算对未来状态的影响。

还是考虑 图2.7 。这个时候 5 都对未来决策造成了影响(3 的位置变成了 c(5,3)+2),(注意这里其实是 5 对 3 的位置造成了影响,和 4 没有任何关系),换句话说对象应该是 所有 p < x < p 2 p<x<p2 p<x<p2 s [ x ] < i s[x]<i s[x]<i 的点,而且对每个 s[x] 的影响恰好为 i − s [ x ] i-s[x] is[x]

综上所述,dp 转移方程为:

  1. f [ i ] [ j ] = f [ i + 1 ] [ j ] + c ( p o s [ i ] , i ) + c ( j , i ) f[i][j]=f[i+1][j]+c(pos[i],i)+c(j,i) f[i][j]=f[i+1][j]+c(pos[i],i)+c(j,i)
  2. f [ i ] [ p o s [ i ] ] = min ⁡ ( f [ i + 1 ] [ j ] + ∑ p o s [ i ] < x < j [ s [ x ] < i ] ( i − s [ x ] ) ∣ j > p o s [ i ] ) f[i][pos[i]]=\min(f[i+1][j]+\sum_{pos[i]<x<j}[s[x]< i](i-s[x])|j>pos[i]) f[i][pos[i]]=min(f[i+1][j]+pos[i]<x<j[s[x]<i](is[x])j>pos[i])

时间复杂度 O ( n 2 ) O(n^2) O(n2) (优秀!)

最后我们写一个 dfs 输出方案即可。

Luogu 唯二 AC 解 (233)

#include<bits/stdc++.h>
#define db double 
#define ll long long
#define mkp make_pair
#define pii pair<int,int> 
#define inf 0x3f3f3f3f
#define fi first
#define se second
using namespace std;
const int Maxn=1005;
pii a[Maxn];
int n,tot,pos[Maxn],s[Maxn],dp[Maxn][Maxn],pre[Maxn],l[Maxn][Maxn],r[Maxn][Maxn],add[Maxn];
pii b[Maxn];
bool cmp(pii x,pii y) {
	return x.fi>y.fi||x.fi==y.fi&&x.se<y.se;
}
void dfs(int i,int j) {
	if(i==n) return;
	if(pos[i]!=j) {
		dfs(i+1,j);
		//输出把当前点的实际位置移动到 j 的实际位置
		tot++;
		b[tot].fi++;
		b[tot].fi+=add[i];
		b[tot].se++;
		//交换到的位置不变 ? 
		for(int k=1;k<=j;k++) {
			if(s[k]<i) b[tot].se++;
		} 
		for(int k=1;k<pos[i];k++) {
			if(s[k]<i) b[tot].fi++;
		}
	}
	else {
		//对后面的决策造成影响 
		for(int k=pos[i]+1;k<pre[i];k++) {
			if(s[k]<i) {
				add[s[k]]+=i-s[k];
			}
		}
		dfs(i+1,pre[i]);
	}
} 
int main() {
	memset(dp,0x3f,sizeof dp);
	cin>>n;
	for(int i=1;i<=n;i++) {
		cin>>a[i].fi;
		a[i].se=i;
	}
	sort(a+1,a+1+n,cmp);
	for(int i=1;i<=n;i++) {
		pos[i]=a[i].se;
		s[a[i].se]=i;
	}
	n++,dp[n][n]=0,s[n]=n;
//	for(int i=1;i<=n;i++) {
//		printf("%d\n",s[i]);
//	}
	for(int i=n;i>=1;i--) {
		int v1=1,v2=1;
		for(int j=1;j<pos[i];j++) {
			if(s[j]<i) {
				v1++;
			}
		}
		for(int j=1;j<=n;j++) {
			if(s[j]<i) {
				v2++;
			}
			if(dp[i+1][j]+v1+v2<dp[i][j]) {
				dp[i][j]=dp[i+1][j]+v1+v2;
				l[i][j]=v1;
				r[i][j]=v2;
			}
		}
		int tmp=0;
		for(int j=pos[i]+1;j<=n;j++) {
			if(dp[i+1][j]+tmp<dp[i][pos[i]]) {
				dp[i][pos[i]]=dp[i+1][j]+tmp;
				pre[i]=j;
			}
			if(s[j]<i) {
				tmp+=i-s[j];
			}
		}
	}
	int ans=inf,xo=0;
	for(int i=1;i<=n;i++) {
		if(dp[1][i]<ans) {
			ans=dp[1][i];
			xo=i;
		}
	}
	dfs(1,xo);
	printf("%d\n",tot);
	for(int i=1;i<=tot;i++) {
		printf("%d %d\n",b[i].fi,b[i].se);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
蛋白质是生物体中普遍存在的一类重要生物大分子,由天然氨基酸通过肽键连接而成。它具有复杂的分子结构和特定的生物功能,是表达生物遗传性状的一类主要物质。 蛋白质的结构可分为四级:一级结构是组成蛋白质多肽链的线性氨基酸序列;二级结构是依靠不同氨基酸之间的C=O和N-H基团间的氢键形成的稳定结构,主要为α螺旋和β折叠;三级结构是通过多个二级结构元素在三维空间的排列所形成的一个蛋白质分子的三维结构;四级结构用于描述由不同多肽链(亚基)间相互作用形成具有功能的蛋白质复合物分子。 蛋白质在生物体内具有多种功能,包括提供能量、维持电解质平衡、信息交流、构成人的身体以及免疫等。例如,蛋白质分解可以为人体提供能量,每克蛋白质能产生4千卡的热能;血液里的蛋白质能帮助维持体内的酸碱平衡和血液的渗透压;蛋白质是组成人体器官组织的重要物质,可以修复受损的器官功能,以及维持细胞的生长和更新;蛋白质也是构成多种生理活性的物质,如免疫球蛋白,具有维持机体正常免疫功能的作用。 蛋白质的合成是指生物按照从脱氧核糖核酸(DNA)转录得到的信使核糖核酸(mRNA)上的遗传信息合成蛋白质的过程。这个过程包括氨基酸的活化、多肽链合成的起始、肽链的延长、肽链的终止和释放以及蛋白质合成后的加工修饰等步骤。 蛋白质降解是指食物中的蛋白质经过蛋白质降解酶的作用降解为多肽和氨基酸然后被人体吸收的过程。这个过程在细胞的生理活动中发挥着极其重要的作用,例如将蛋白质降解后成为小分子的氨基酸,并被循环利用;处理错误折叠的蛋白质以及多余组分,使之降解,以防机体产生错误应答。 总的来说,蛋白质是生物体内不可或缺的一类重要物质,对于维持生物体的正常生理功能具有至关重要的作用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值