题目链接
LOJ#10003. 「一本通 1.1 例 4」加工生产调度
解题思路
本题可采用Johnson算法
在本题中,将任务以
m
i
n
(
a
i
,
b
i
)
min(a_i,b_i)
min(ai,bi)排序后,将
a
i
≤
b
i
a_i\leq b_i
ai≤bi的任务顺序放在工作队列的前部,将
a
i
>
b
i
a_i>b_i
ai>bi的任务逆序放在序列的后部。下面会通过证明,来说明这样可以得到最优解。
证明(大量数学,慎入)
设
T
【
S
,
t
】
T【S,t】
T【S,t】表示
t
t
t时刻后B机器可以加工A机器加工完的零件集合
S
=
{
J
1
,
J
2
,
.
.
.
,
J
n
}
S=\{J_1,J_2,...,J_n\}
S={J1,J2,...,Jn},这样的话,
S
S
S全部加工完所需的最短时间。
有
T
【
S
,
t
】
=
m
i
n
(
a
i
+
T
【
S
−
{
J
i
}
,
b
i
+
m
a
x
(
0
,
t
−
a
i
)
】
)
T【S,t】=min(a_i+T【S-\{J_i\},b_i+max(0,t-a_i)】)
T【S,t】=min(ai+T【S−{Ji},bi+max(0,t−ai)】)
设若
i
i
i工件在
j
j
j工件前处理能得到更优解,则我们有
T
【
S
,
t
】
=
a
i
+
T
【
S
−
{
J
i
}
,
b
i
+
m
a
x
(
0
,
t
−
a
i
)
】
T【S,t】=a_i+T【S-\{J_i\},b_i+max(0,t-a_i)】
T【S,t】=ai+T【S−{Ji},bi+max(0,t−ai)】
=
a
i
+
a
j
+
T
【
S
−
{
J
i
,
J
j
}
,
b
j
+
m
a
x
(
b
i
+
m
a
x
(
0
,
t
−
a
i
)
−
a
j
,
0
)
】
=a_i+a_j+T【S-\{J_i,J_j\},b_j+max(b_i+max(0,t-a_i)-a_j,0)】
=ai+aj+T【S−{Ji,Jj},bj+max(bi+max(0,t−ai)−aj,0)】
=
a
i
+
a
j
+
T
【
S
−
{
J
i
,
J
j
}
,
T
i
j
】
=a_i+a_j+T【S-\{J_i,J_j\},T_{ij}】
=ai+aj+T【S−{Ji,Jj},Tij】
其中
T
i
j
=
b
j
+
m
a
x
(
b
i
+
m
a
x
(
0
,
t
−
a
i
)
−
a
j
,
0
)
T_{ij}=b_j+max(b_i+max(0,t-a_i)-a_j,0)
Tij=bj+max(bi+max(0,t−ai)−aj,0)
=
b
i
+
b
j
−
a
j
+
m
a
x
(
0
,
t
−
a
i
,
a
j
−
b
i
)
=b_i+b_j-a_j+max(0,t-a_i,a_j-b_i)
=bi+bj−aj+max(0,t−ai,aj−bi)
=
b
i
+
b
j
−
a
i
−
a
j
+
m
a
x
(
a
i
,
t
,
a
i
+
a
j
−
b
i
)
=b_i+b_j-a_i-a_j+max(a_i,t,a_i+a_j-b_i)
=bi+bj−ai−aj+max(ai,t,ai+aj−bi)
好,化简到这一步,我们采取贪心的常用方法:
若调换
i
i
i,
j
j
j顺序,有
T
′
【
S
,
t
】
=
a
i
+
a
j
+
T
【
S
−
{
J
i
,
J
j
}
,
T
j
i
】
T'【S,t】=a_i+a_j+T【S-\{J_i,J_j\},T_{ji}】
T′【S,t】=ai+aj+T【S−{Ji,Jj},Tji】
其中
T
j
i
=
b
i
+
b
j
−
a
i
−
a
j
+
m
a
x
(
a
j
,
t
,
a
i
+
a
j
−
b
j
)
T_{ji}=b_i+b_j-a_i-a_j+max(a_j,t,a_i+a_j-b_j)
Tji=bi+bj−ai−aj+max(aj,t,ai+aj−bj)
根据题设有
T
≤
T
′
T\leq T'
T≤T′
故
m
a
x
(
a
i
,
t
,
a
i
+
a
j
−
b
i
)
≤
m
a
x
(
a
j
,
t
,
a
i
+
a
j
−
b
j
)
max(a_i,t,a_i+a_j-b_i)\leq max(a_j,t,a_i+a_j-b_j)
max(ai,t,ai+aj−bi)≤max(aj,t,ai+aj−bj)
其中两边的
t
t
t相同,不影响答案,故
m
a
x
(
a
i
,
a
i
+
a
j
−
b
i
)
≤
m
a
x
(
a
j
,
a
i
+
a
j
−
b
j
)
max(a_i,a_i+a_j-b_i)\leq max(a_j,a_i+a_j-b_j)
max(ai,ai+aj−bi)≤max(aj,ai+aj−bj)
a
i
+
a
j
+
m
a
x
(
−
a
j
,
−
b
i
)
≤
a
i
+
a
j
+
m
a
x
(
−
a
i
,
−
b
j
)
a_i+a_j+max(-a_j,-b_i)\leq a_i+a_j+max(-a_i,-b_j)
ai+aj+max(−aj,−bi)≤ai+aj+max(−ai,−bj)
m
a
x
(
−
a
j
,
−
b
i
)
≤
m
a
x
(
−
a
i
,
−
b
j
)
max(-a_j,-b_i)\leq max(-a_i,-b_j)
max(−aj,−bi)≤max(−ai,−bj)
m
i
n
(
a
i
,
b
j
)
≤
m
i
n
(
a
j
,
b
i
)
min(a_i,b_j)\leq min(a_j,b_i)
min(ai,bj)≤min(aj,bi)
okk
我们得到了这么个简单式子。
解释解释
有
a
i
≤
a
j
,
a
i
≤
b
i
,
b
j
≤
a
j
,
b
j
≤
b
i
a_i\leq a_j,a_i\leq b_i,b_j\leq a_j,b_j\leq b_i
ai≤aj,ai≤bi,bj≤aj,bj≤bi
这几个条件中必定满足至少一个(特别关注第一个、第四个)
这样,我们就能从感性上理解Johnson算法了
详细代码
#define USEFASTERREAD 1
#define rg register
#define inl inline
#define DEBUG printf("[Passing [%s] in line %d.]\n", __func__, __LINE__)
#define putline putchar('\n')
#define putsp putchar(' ')
#define Rep(a, s, t) for(rg int a = s; a <= t; a++)
#define Repdown(a, t, s) for(rg int a = t; a >= s; a--)
typedef long long ll;
#include<cstdio>
#if USEFASTERREAD
char In[1 << 20], *ss = In, *tt = In;
#define getchar() (ss == tt && (tt = (ss = In) + fread(In, 1, 1 << 20, stdin), ss == tt) ? EOF : *ss++)
#endif
struct IO {
void RS() {freopen("test.in", "r", stdin), freopen("test.out", "w", stdout);}
template<typename T> inline IO r(T& x)const {
x = 0; T f = 1; char ch = getchar();
for(; ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') f = -1;
for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + int(ch - '0');
x *= f; return *this;
}
template<typename T> inline IO w(T x)const {
if(x < 0) {putchar('-'); x = -x;}
if(x >= 10) w(x / 10);
putchar(x % 10 + '0'); return *this;
}
template<typename T> inline IO wl(const T& x)const {w(x), putline; return *this;}
template<typename T> inline IO ws(const T& x)const {w(x), putsp; return *this;}
inline IO l() {putline; return *this;}
inline IO s() {putsp; return *this;}
}io;
template<typename T> inline T Max(const T& x, const T& y) {return y < x ? x : y;}
template<typename T> inline T Min(const T& x, const T& y) {return y < x ? y : x;}
template<typename T> inline void Swap(T& x, T& y) {T tmp = x; x = y; y = tmp;}
template<typename T> inline T Abs(const T& x) {return x > 0 ? x : -x;}
#include<algorithm>
using namespace std;
const int MAXN = 1005;
int n;
int a[MAXN];
int b[MAXN];
int m[MAXN];
int id[MAXN];
int ans[MAXN];
bool cmp(int x, int y) {
return m[x] < m[y];
}
int main() {
//io.RS();
io.r(n);
for(rg int i = 1; i <= n; i++)
io.r(a[i]);
for(rg int i = 1; i <= n; i++)
io.r(b[i]);
for(rg int i = 1; i <= n; i++) {
m[i] = Min(a[i], b[i]);
id[i] = i;
}
sort(id + 1, id + 1 + n, cmp);
int l = 1, r = n;
for(rg int i = 1; i <= n; i++) {
int now = id[i];
if(m[now] == a[now]) ans[l++] = now;
else ans[r--] = now;
}
int at = 0, tt = 0;
for(rg int i = 1; i <= n; i++) {
at += a[ans[i]];
if(tt < at) tt = at;
tt += b[ans[i]];
}
io.wl(tt);
for(rg int i = 1; i <= n; i++) {
io.w(ans[i]);
if(i != n) io.s();
}
return 0;
}
Update
哪要推这么多。。。啊我有病
Irressey 的洛谷博客