问题&数据输入&数据输出:
分析:
首先将任务按其截止时间非减序排序。
对任务 1 , 2 , …… , i,如果截止时间为 d ,则最小误时惩罚为 p( i , d ) 。
其中 p( i , d ) = min{ p(i-1, d)+wi , p(i-1, min{d, di}-ti) }
p(i-1, d)+wi 表示决定不做第 i 个任务,p(i-1, min{d, di}-ti) 表示决定要做第 i 个任务,这时必须在第 i 个任务的截至时间前做完它(即 min{d, di}-ti )
思路:
先将任务集按照结束时间非递减排序。
设置数组p[ ][ ]来保存 p( i , d )的结果(本算法的局限性:时间只能为整数值)。
对于第一个任务来说,如果时间少于它需要执行的时间 t,则会遭受惩罚——p[1][ 0 ~ tasks[1].t ]=tasks[i].w;
时间够则不然——p[1][ 0 - tasks[1].t ]=0。
对于第 i 个任务 的任务来说( i 取 2 - n),就如果时间少于它需要执行的时间 t,则不能执行它了,只能放弃——p[ i ][ 0 ~ tasks[1].t ]=p(i-1, d)+wi;
如果时间够,则看是执行了好还是不执行好——p[ i ][ tasks[1].t ~ maxTime ] = min{ p(i-1, d)+wi , p(i-1, min{d, di}-ti) }。
代码:
#include<iostream>
#include<fstream>
#define Max 99
using namespace std;
struct Task {
int t; //完成任务需要的时间
int d; //截止时间
int w; //误时惩罚
};
void quickSort(Task s[], int l, int r)
{//快速排序,不是重点
if (l < r)
{
int i = l, j = r;
Task x = s[l];
while (i < j)
{
while (i < j && s[j].d >= x.d)
j--;
if (i < j)
s[i++] = s[j];
while (i < j && s[i].d < x.d)
i++;
if (i < j)
s[j--] = s[i];
}
s[i] = x;
quickSort(s, l, i - 1);
quickSort(s, i + 1, r);
}
}
int min(int a, int b)
{return (a > b) ? b : a;
}
void main()
{
ifstream input("input.txt");
ofstream output("output.txt");
int n;
input >> n;
Task *tasks = new Task[n + 1];
for (int i = 1; i <= n; i++)
{
input >> tasks[i].t >> tasks[i].d >> tasks[i].w;
}
//按截至时间非递减排序
quickSort(tasks, 1, n);
int p[500][500];
//先初始化
for (int i = 1; i <= n; i++)
{
for (int j = 0; j < tasks[n].d; j++)
{
p[i][j] = Max;
}
}
//任务 1,没有更前面的任务了,单独讨论
for (int i = 0; i <= tasks[n].d; i++)
{
if (i < tasks[1].t)//如果没给够时间
{
p[1][i] = tasks[1].w;//罚
}
else
{
p[1][i] = 0;
}
}
for (int i = 2; i <= n; i++)
{
for (int j = 0; j <= tasks[n].d; j++)
{
int a = p[i - 1][j] + tasks[i].w;
int b = p[i - 1][min(j, tasks[i].d) - tasks[i].t];
if (j < tasks[i].t)
{
p[i][j] = a;
}
else
{
if (a < b)
p[i][j] = a;
else
p[i][j] = b;
}
}
}
cout << p[n][tasks[n].d] << endl;
cin >> n;
input.close();
output.close();
}