临项交换法在贪心算法中的应用

1.排序不等式的证明

我们给出一个高中常见的排序不等式:

\(a_1\leq a_2\leq ...... \leq a_n\)\(b_1 \leq b_2 \leq ...... \leq b_n\)

\(a_{t_1},a_{t_2}, ...... ,a_{t_{n-1}},a_{t_n}\)是数列\(\left\{ a_n \right\}\)的一个随机排列,

那么有如下不等式成立:

\[a_nb_1+a_{n-1}b_2+......+a_nb_1\leq a_{t_1}b_1+a_{t_2}b_2+......+a_{t_n}b_n\leq a_1b_1+a_2b_2+......+a_nb_n \]

即 逆序和 \(\leq\) 乱序和 \(\leq\) 顺序和

其证明可以通过 临项交换法 进行:

对于顺序和,随机挑选\(i,j(i<j)\)两项进行交换,即将\(a_ib_i+a_jb_j\)交换为\(a_ib_j+a_jb_i\)

那么

\[(a_ib_i+a_jb_j)-(a_ib_j+a_jb_i)=(a_j-a_i)(b_j-b_i)\geq 0 \]

可以说明对于顺序和,任意选择两项进行交换都不会使得值更大

将其进行推广,可以得出顺序和最大

同理,对于逆序和,任意选择两项交换都不会使得值更小,推广后得到逆序和最小

这样我们便证明了上述结论

上述证明的核心在于 临项交换法:对一个按某种顺序排列的序列,证明任意两项交换后都不会使得答案更优,则该顺序排列是最优解,或者说,当两项按某种顺序排列后最优,大概率可以推广到\(n\)项。这种方法常常用于以排序为基础的贪心题的证明。

2.临项交换在贪心法中的应用——NOIP2012 国王游戏

链接

本来这个题目是蓝题的,结果因为太经典,做的人太多,已经变成绿题了就离谱

思路

记皇帝是第0个人,第\(i\)个人所得金币数量为\(v_i\),那么有

\[v_i=\frac{\prod_{k=0}^{i-1}a_k}{b_i} \]

我们的目标是使得\(ans=max\left\{ v_1,v_2,......,v_n \right\}\)最小

临项交换:我们先按某种方式进行排序,随后随意抽取相邻两项\((i,i+1)\)尝试交换。

原本答案为\(ans=max(ans0,\frac{\prod_{k=0}^{i-1}a_k}{b_i},\frac{\prod_{k=0}^{i}a_k}{b_{i+1}})\)

交换后变为\(ans=max(ans0,\frac{\prod_{k=0}^{i-1}a_k}{b_{i+1}},\frac{(\prod_{k=0}^{i-1}a_k)*a_{k+1}}{b_i})\)

那么我们比较一下\(\frac{\prod_{k=0}^{i}a_k}{b_{i+1}}\)\(\frac{(\prod_{k=0}^{i-1}a_k)*a_{k+1}}{b_i}\)的大小即可

约去公因式,即比较\(\frac{a_k}{b_{i+1}}\)\(\frac{a_{i+1}}{b_i}\)即可

\(a_ib_i\leq a_{i+1}b_{i+1}\)时,此时\(ans1\)不会大于\(ans2\),无需交换,否则交换后可以使答案不会变差(甚至变优)

那么我们就得到了一个排序思路:以\(a_ib_i\)作为排序依据,从小到大排序即可

代码

略,洛谷题解挺多的了(这题好像还要写一下高精度才能完全AC)

补充题目

1.2019年河海ACM选拔赛低年级组H题 刷题狂魔

可以看下我前面写的博客

2.洛谷P1012 拼数

临项交换法:把\(n\)个数字按照字符串读入,按某一顺序排列,尝试将相邻两项\((a,b)\)进行交换,可以发现当\(a+b\geq b+a\)(注意,这里时按照字符串方式进行加减,类似于拼接,而不是算术加法)时无需交换,反之交换后可以使得答案更优。代码如下:

#include<bits/stdc++.h>
using namespace std;
string a[21];
bool cmp(string a,string b){
    return a+b>b+a;
}
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)cin>>a[i];
    sort(a+1,a+n+1,cmp);
    for(int i=1;i<=n;i++)cout<<a[i];
    return 0;
}
posted @ 2020-12-23 00:14  cyhforlight  阅读(341)  评论(0编辑  收藏  举报