Johnson法则证明
在这里先不务正业两句,当我和同机房的某位神犇努力钻研证明过程的时候,非常
气愤为什么编书者如此不负责任的只摆几个看不懂的式子,但是当我们抠懂了之后
书上写的真好
不务正业到此结束
现在开始算法证明:
首先如果不知道什么是Johnson法则的可以看《提高篇》第13页,
那里同时也有一篇较为不易理解的证明(也是我写这篇文章的目的)
首先说一个东西叫做“交换论证”
“交换论证”是什么东西呢:
交换论证主要的思想也就是先假设存在一个最优的算法和我们的贪心算法最接近,
然后通过交换两个算法里的一个步骤(或元素),得到一个新的最优的算法,同时
这个算法比前一个最优算法更接近于我们的贪心算法,从而得到矛盾,原命题成立。
以上源自“博客园的一位大佬 文章链接”
以下为我举的一个例子
假设现在要做a和b两件事,先做a,再做b 的时间为 T(a,b),那么如果反过来就是 T(b,a)。
我为使 T(a,b) < T(b,a) 得到限定条件(算法),然后按照这个限定条件运行程序,OK。
上面的看不懂也没关系
Johnson法则的证明就运用的交换论证:
S={任务们;}其实S就是个结构体,a是A机器做任务时间,b是B机器的;
现在的最优调度。若在这个调度中,安排在最前面的两个作业分别是i和j。
然后就要上图了
图是啥意思:A机器开始加工S中的任务,而B机器还在加工其它部件,t时间后B机器开始加工S中的任务; 再说一下,可以想一想,A机器从开机就一刻不停的工作,B机器开机时间一定比A晚(因为A要先做),A机器的结束时间是一定的(a中所有数的和),而B机器则不是,这是因为B机器要等待A机器加工完才能做,B机器可能会出现长短不一的等待时间,所以我们的目的是什么
目的就是:使得B机器"不干活“的时间最短(上面一段没看懂的可以多看几遍)。
现在开始第一步(列式子):
第二步(化简式子):
第三步(算):
最后一个式子就是Johnson算法的数学表达式
当然这道题就迎刃而解了
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int n,ans;
struct Node{
int a,b,c;
}x[1500];
bool cmp(Node x,Node y){
return min(y.b,x.a)<min(x.b,y.a);//这就是Johnson表达式
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&x[i].a);
for(int i=1;i<=n;i++) {scanf("%d",&x[i].b);x[i].c=i;};
sort(x+1,x+n+1,cmp);
int ta=0,tb=0;
for(int i=1;i<=n;i++){
ta+=x[i].a;
tb=max(ta,tb)+x[i].b;
}
printf("%d\n",tb);
for(int i=1;i<=n;i++) printf("%d ",x[i].c);
return 0;
}
注:这篇文章的大部分图片中的大部分文字皆为本机房大佬cainai出品。