用2台处理机A和B处理n个作业。设第i个作业交给机器A处理时需要时间 ai a i ,若由机器B来处理,则需要时间 bi b i 。由于各作业的特点和机器的性能关系,很可能对于某些i,有 ai≥bi a i ≥ b i ,而对于某些j,j≠i,有 aj<bj a j < b j 。既不能将一个作业分开由2台机器处理,也没有一台机器能同时处理2个作业。设计一个动态规划算法,使得这2台机器处理完这n个作业的时间最短(从任何一台机器开工到最后一台机器停工的总时间)。研究一个实例: (a1,a2,a3,a4,a5,a6)=(2,5,7,10,5,2);(b1,b2,b3,b4,b5,b6)=(3,8,4,11,3,4) ( a 1 , a 2 , a 3 , a 4 , a 5 , a 6 ) = ( 2 , 5 , 7 , 10 , 5 , 2 ) ; ( b 1 , b 2 , b 3 , b 4 , b 5 , b 6 ) = ( 3 , 8 , 4 , 11 , 3 , 4 ) 。
对于给定的2 台处理机A和B处理n个作业,找出一个最优调度方案,使2台机器处理完这n个作业的时间最短。
数据输入
输入数据的第1行是1个正整数n(n≤200), 表示要处理n个作业。接下来的2行中,每行有n个正整数,分别表示处理机A和B处理第i个作业需要的处理时间。
对于n个作业中的每个作业,要么由机器A处理,要么由机器B处理。可以设计一个n位的二进制序列,某一位上为1,由机器A处理,为0由机器B处理。机器A、机器B处理n个作业的所有情况,对应于该n位二进制的全排列。可见,可以转化为n位二进制全排列问题,共有 2n 2 n 种情况。
假设 p(i,j,k) p ( i , j , k ) 表示前 k k 个任务在机器A处理不超过时间 i i ,机器B处理不超过时间 j j 内完成,为boolean型。
p(i,j,k)=p(i−ak,j,k−1)||p(i,j−bk,k−1) p ( i , j , k ) = p ( i − a k , j , k − 1 ) | | p ( i , j − b k , k − 1 ) 前提是 i>=ak,j>=bk i >= a k , j >= b k
p(i,j,0)=1 p ( i , j , 0 ) = 1
最终的最短处理时间为 min{max{i, j}}
假设T[i][j],表示 完成 前i个任务,在机器A花费小于等于j的时间的前提下,机器B所需要花费的最少时间。
1.如果时间j小于a[i],那么第i个任务只可能由机器B完成:T[i][j] = T[i-1][j] + b[i];
2.如果时间j大于或等于a[i],那么须要考虑第i个任务是由机器A还是由机器B处理好:
(1)若由机器A处理:T[i][j] = T[i-1][j-a[i]]
(2)若由机器B处理:T[i][j] = T[i-1][j] + b[i]
可见此时,T[i][j] = MIN{T[i-1][j-a[i]], T[i-1][j] + b[i]}
最后,比较 j与T[n][j],取较大者(机器A、机器B最后都要处理完成),即:MAX{j, T[n][j]}
遍历j的所有情况,取最小者,即:MIN{MAX{j, T[n][j]}} 0<=j<=sum
sum为机器A单独完成所有任务所须花费的时间
注意:机器A与机器B花费的时间先分开考虑
import java.util.Scanner;
public class DuLiRenWuZuiYouDiaoDu {
public static void main(String[] args){
int[] a,b;
int n,i,j,temp;
int result = 10000;
int sa,sb;
/*
input data:
6
2 5 7 10 5 2
3 8 4 11 3 4
*/
Scanner input = new Scanner(System.in);
while (true){
n = input.nextInt();
a=new int[n];
b=new int[n];
for(i=0;ifor(i=0;i//n位二进制的全排列,000000 --> 111111,假设为1时,A机处理;为0时,B机处理
for(i=0;i2,n);i++)
{
sa=0;sb=0;temp=i;
// for(j=0; j
for(j=n-1; j>=0; j--)
{
if(temp%2 == 1) //最后一位为1,A机处理
sa += a[j];
else
sb += b[j]; //最后一位为0,B机处理
temp = temp/2; //可以看成二进制右移一位
}
temp = sa > sb ? sa : sb;
result = result > temp ? temp : result;
}
System.out.println(result);
}
}
}
import java.util.Scanner;
public class DuLiRenWuZuiYouDiaoDu1 {
private static int n;
private static int[] a;
private static int[] b;
private static boolean[][][] p;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (true){
n = sc.nextInt();
a = new int[n + 1];
b = new int[n + 1];
for (int i = 1; i <= n; i++) {
a[i] = sc.nextInt();
}
for (int i = 1; i <= n; i++) {
b[i] = sc.nextInt();
}
int max1 = getMaxValue(a, n);
int max2 = getMaxValue(b, n);
int mx = max(max1, max2); //单个作业完成任务所需时间最大值
int mn = mx * n; //所有任务完成时间上限
p = new boolean[mn + 1][mn + 1][n + 1];
int result = schedule(n, mn);
System.out.println(result);
}
}
/*
假设p(i, j, k)表示前k个任务在机器A处理不超过时间i,在机器B处理不超过时间j内完成,为boolean型
p(i, j, k) = p(i-ak, j, k-1) || p(i, j-bk, k-1) 前提是i>=ak, j>=bk
p(i, j, 0) = 1
最短处理时间为 min{max{i, j}}
*/
private static int schedule(int n, int mn) {
for (int i = 0; i <= mn; i++)
for (int j = 0; j <= mn; j++) {
p[i][j][0] = true;
for (int k = 1; k <= n; k++)
p[i][j][k] = false;
}
for (int k = 1; k <= n; k++)
for (int i = 0; i <= mn; i++)
for (int j = 0; j <= mn; j++) {
if (i >= a[k])
p[i][j][k] = p[i - a[k]][j][k - 1];
if (j >= b[k])
p[i][j][k] = (p[i][j][k] || p[i][j - b[k]][k - 1]);
}
int opt = mn;
int temp;
for (int i = 0; i <= mn; i++)
for (int j = 0; j <= mn; j++)
if (p[i][j][n]) {
temp = max(i, j);
if (temp < opt)
opt = temp;
}
return opt;
}
//返回数组c[1,n]中的最大值
private static int getMaxValue(int c[], int n) {
int mx = c[1];
for (int i = 2; i <= n; i++)
if (c[i] > mx)
mx = c[i];
return mx;
}
private static int max(int a, int b) {
return a > b ? a : b;
}
}
import java.util.Scanner;
public class DuLiRenWuZuiYouDiaoDu3 {
private static int[][] T;
private static int[] a;
private static int[] b;
/*
注意:机器A与机器B花费的时间先分开考虑
假设T[i][j],表示 完成 前i个任务,在机器A花费小于等于j的时间的前提下,机器B所需要花费的最少时间。
1.如果时间j小于a[i],那么第i个任务只可能由机器B完成:T[i][j] = T[i-1][j] + b[i];
2.如果时间j大于或等于a[i],那么须要考虑第i个任务是由机器A还是由机器B处理好:
1)若由机器A处理:T[i][j] = T[i-1][j-a[i]]
2)若由机器B处理:T[i][j] = T[i-1][j] + b[i]
可见此时,T[i][j] = MIN{T[i-1][j-a[i]], T[i-1][j] + b[i]}
最后,比较 j与T[n][j],取较大者(机器A、机器B最后都要处理完成),即:MAX{j, T[n][j]}
遍历j的所有情况,取最小者,即:MIN{MAX{j, T[n][j]}} 0<=j<=sum sum为机器A单独完成所有任务所须花费的时间
*/
public static void main(String[] args) {
int i, j, n;
int sum, time;
Scanner input = new Scanner(System.in);
while (true) {
sum = 0;
n = input.nextInt();
a = new int[n + 1];
b = new int[n + 1];
T = new int[100][100];
for (i = 1; i <= n; i++) {
a[i] = input.nextInt();
sum += a[i];
}
for (i = 1; i <= n; i++) {
b[i] = input.nextInt();
}
for(i=1; i<=n; i++)
for(j=0; j<=sum; j++)
if(j >= a[i])
T[i][j] = MIN(T[i-1][j-a[i]], T[i-1][j]+b[i]);
else
T[i][j] = T[i-1][j] + b[i];
time = Integer.MAX_VALUE;
for (j = 0; j <= sum; j++)
time = MIN(time, MAX(j, T[n][j]));
System.out.println(time);
}
}
private static int MAX(int a, int b) {
return a > b ? a : b;
}
private static int MIN(int a, int b) {
return a > b ? b : a;
}
}
import java.util.Scanner;
public class DuLiRenWuZuiYouDiaoDu2 {
private static int[] T;
private static int[] a;
private static int[] b;
public static void main(String[] args) {
int i, j, n;
int sum, ans;
Scanner input = new Scanner(System.in);
while (true) {
sum = 0;
n = input.nextInt();
a = new int[n + 1];
b = new int[n + 1];
T = new int[1000];
for (i = 1; i <= n; i++) {
a[i] = input.nextInt();
sum += a[i];
}
for (i = 1; i <= n; i++) {
b[i] = input.nextInt();
}
for (i = 1; i <= n; i++)
for (j = sum; j >= 0; j--)
if (j >= a[i])
T[j] = MIN(T[j - a[i]], T[j] + b[i]);
else
T[j] = T[j] + b[i];
ans = Integer.MAX_VALUE;
for (j = 0; j <= sum; j++)
ans = MIN(ans, MAX(j, T[j]));
System.out.println(ans);
}
}
private static int MAX(int a, int b) {
return a > b ? a : b;
}
private static int MIN(int a, int b) {
return a > b ? b : a;
}
}
6
2 5 7 10 5 2
3 8 4 11 3 4
15
王晓东《计算机算法设计与分析》(第3版)P88