问题描述:
有兄弟二人做n道题目。
已知哥哥做题目i需要时间ai,弟弟做题目i需要时间bi 。
由于兄弟二人对知识掌握的程度不同,很可能对于某些 i,有 ai ≥ bi ,而对于某些 j,j≠i,有 aj < bj 。
每一道题目只能交给二人中的一个来做。
设计一个算法,使得二人解掉所有题目所用的时间最短(从任何一人开始做题到最后一人解掉最后一道题目的总时间)。
研究一个实例: (a1,a2,a3,a4,a5,a6)=(2,5,7,10,5,2);(b1,b2,b3,b4,b5,b6)=(3,8,4,11,3,4)。
数据输入:
输入的第 1 行是 1 个正整数 n, 表示要处理 n 个作业。 接下来的 2 行中,每行有 n 个正整数,ai和bi。
结果输出:
输出计算出的最短解题时间。
样例输入:
6 2 5 7 10 5 2 3 8 4 11 3 4
样例输出:
15
代码:
#include <iostream>
#include<string.h>
using namespace std;
const int INTMAX = 0x7fffffff;
int n;
int* a, * b;
const int get_min_time_dyna_1d()
{
const int n = ::n; //防止求解过程中修改n、a、b
const int* a = ::a;
const int* b = ::b;
int i, k;
int* p; //p[i]=j表示所有任务由a完成不超过i时间,由b完成不超过j时间
int ret;
int sum_a = 0, sum_b = 0; //存储任务完全由a/b机器完成所需要花费的时间
for (i = 0; i < n; i++)
{
sum_a += a[i];
sum_b += b[i];
}
try
{
p = new int[sum_a + 1];
}
catch (const std::exception& e)
{
cerr << "内存申请失败!" << e.what() << endl;
return -1;
}
for (i = 0; i <= sum_a; i++)
p[i] = 0; //初始化,假设任务全由a完成
for (k = 0; k < n; k++)
{ //每次循环完成一件任务
for (i = sum_a; i >= 0; i--)
{ //初始化时,任务全由a完成
p[i] = p[i] + b[k]; //初始化,把任务k派给b机器
if (i >= a[k]) //如果a机器在i时间也可以完成任务k
p[i] = p[i] < p[i - a[k]] ? p[i] : p[i - a[k]];
}
}
for (i = 0, ret = INTMAX; i <= sum_a; i++)
{
int temp = i > p[i] ? i : p[i];
if (temp < ret)
ret = temp;
}
delete[]p;
return ret;
}
const int get_min_time_dyna_2d()
{
const int n = ::n;
const int* a = ::a;
const int* b = ::b;
int i, k;
int** p; //p[i]=j表示所有任务由a完成不超过i时间,由b完成不超过j时间
int ret;
int sum_a = 0; //存储任务完全由a机器完成所需要花费的时间
for (i = 0; i < n; i++)
sum_a += a[i];
const int total_sum_a = sum_a; //记录a的任务时间总和
try
{
p = new int* [total_sum_a + 1];
for (i = 0; i <= total_sum_a; i++)
{
p[i] = new int[n + 1];
memset(p[i], 0, (n + 1) * sizeof(int)); //初始全部置0
}
}
catch (const std::exception& e)
{
cerr << "内存申请失败!" << e.what() << endl;
return -1;
}
for (k = 1, sum_a = 0; k <= n; k++)
{
//k表示当前完成到第几个任务。作下标使用需要-1
sum_a += a[k - 1];
for (i = 0; i < sum_a; i++)
{ //i=sum_a时不用算,因为p一定是0
p[i][k] = p[i][k - 1] + b[k - 1];
if (i >= a[k - 1])
p[i][k] = p[i][k] < p[i - a[k - 1]][k - 1] ? p[i][k] : p[i - a[k - 1]][k - 1];
}
}
for (i = 0, ret = INTMAX; i <= total_sum_a; i++)
{
int max_ij = i > p[i][n] ? i : p[i][n];
if (max_ij < ret)
ret = max_ij;
}
for (i = 0; i <= total_sum_a; i++)
delete[]p[i];
delete[]p;
return ret;
}
const int get_min_time_dyna_3d()
{
const int n = ::n;
const int* a = ::a;
const int* b = ::b;
int i, j, k;
bool*** p;
int sum_a = 0, sum_b = 0; //存储任务完全由a/b机器完成所需要花费的时间
for (i = 0; i < n; i++)
{
sum_a += a[i];
sum_b += b[i];
}
int ret;
try
{
p = new bool** [sum_a + 1];
for (i = 0; i <= sum_a; i++)
p[i] = new bool* [sum_b + 1];
for (i = 0; i <= sum_a; i++)
for (j = 0; j <= sum_b; j++)
p[i][j] = new bool[n + 1];
}
catch (const std::exception& e)
{
cerr << "内存申请失败!" << e.what() << endl;
return -1;
}
for (i = 0; i <= sum_a; i++)
{
for (j = 0; j <= sum_b; j++)
{
p[i][j][0] = true;
for (k = 1; k <= n; k++)
p[i][j][k] = false;
}
}
for (k = 1; k <= n; k++)
{
for (i = 0; i <= sum_a; i++)
{
for (j = 0; j <= sum_b; j++)
{
if (i - a[k - 1] >= 0)
p[i][j][k] = p[i - a[k - 1]][j][k - 1];
if (j - b[k - 1] >= 0)
p[i][j][k] = p[i][j][k] || p[i][j - b[k - 1]][k - 1];
}
}
}
for (i = 0, ret = INTMAX; i <= sum_a; i++)
{
for (j = 0; j <= sum_b; j++)
{
if (p[i][j][n])
{
int tmp = (i > j) ? i : j;
if (tmp < ret)
ret = tmp;
}
}
}
for (i = 0; i <= sum_a; i++)
{
for (j = 0; j <= sum_b; j++)
delete[] p[i][j];
delete[]p[i];
}
delete[]p;
return ret;
}
int main()
{
cin >> n;
try
{
a = new int[n];
b = new int[n];
}
catch (const std::exception& e)
{
cerr << "内存申请失败!" << e.what() << endl;
return -1;
}
for (int i = 0; i < n; i++)
cin >> a[i];
for (int i = 0; i < n; i++)
cin >> b[i];
cout << get_min_time_dyna_1d() << endl;
delete[]a;
delete[]b;
return 0;
}
仅供学习,搬运注明出处!