您的位置:首页 > 编程语言 > C语言/C++

算法导论——16.1-5动态规划解决活动选择带值问题

2017-03-28 20:54 211 查看
原活动问题是用贪心算法解得,实质是就是不重合区间择多问题。

新的问题变形后,每个区间的都带上的值,求如何选择才能得到不重合区间且值最大。

想了想只能用dp来解决,下面附我的解题思路+代码

       1.用act[max][3]记录所有活动的状态(开始时间|结束时间|价值)

         act[n-1][0]表示第n个活动的开始时间,act[n-1][1]]表示第n个活动的结束时间,act[n-1][2],表示第n个活动的价值

       2.用maxVal[max][2]记录所有活动的最大价值(最大价值和|结束时间)

       3.预处理,将act活动按照结束时间来排序,从小到大

       4.for(maxVal[i] 表示当前活动 从 0 ~ count)

                maxVal[i][0] = act[i][2];//将活动最大值和设为当前活动价值

                maxVal[i][1] = act[i][1];//将活动结束点设为当前活动结束点

                for(act[j] 表示之前活动 从 当前活动-1 ~ 0)

                     //当前活动开始时间 >= 之前活动结束时间 && 当前活动最大值和< 之前活动最大值和+当前活动最大值

                    //当前活动可以接上之前活动 并且 当前活动接上之前活动后的最大值和大于当前活动之前的最大值和

                     if (atv[i][0] >= maxVal[j][1] && maxVal[i][0] < maxVal[j][0] + atv[j][2])

                                 maxVal[i][0] = maxVal[j][0] + atv[j][2];//当前活动最大值和更新为之前活动最大值和+当前活动最大值

                                 maxVal[i][1] = atv[i][1];//更新最大价值结束点为当前活动结束点

                                 break;

                      //不能接上前面活动&&当前活动最大价值<前面活动最大价值

                     else if (atv[i][0] < maxVal[j][1] && maxVal[i][0] < maxVal[j][0])

                                 maxVal[i][0] = maxVal[j][0];  //更新当前活动最大价值为前面活动的最大价值,

                                 maxVal[i][1] = maxVal[j][1];//更新当前活动最大值结束时间为前面活动最大值结束时间

只是考虑两种情况会更新maxVal

由于每次遍历都可以得到最大价值点,所以就不用遍历所有先前节点,这样可以保证算法复杂度在O(nlog2n)          

下面是c++源代码,如果有不对的地方,欢迎指正

#include <stdio.h>
using namespace std;
#pragma warning(disable:4996)
//预处理,按结束时间排序
void preDeal(int arr[][3], int len){
for (int i = len - 1; i > 0; i--){
for (int j = 0; j < i; j++){
if (arr[j][1]>arr[j + 1][1]){
arr[j][0] += arr[j + 1][0];
arr[j][1] += arr[j + 1][1];
arr[j][2] += arr[j + 1][2];
arr[j + 1][0] = arr[j][0] - arr[j + 1][0];
arr[j + 1][1] = arr[j][1] - arr[j + 1][1];
arr[j + 1][2] = arr[j][2] - arr[j + 1][2];
arr[j][0] -= arr[j + 1][0];
arr[j][1] -= arr[j + 1][1];
arr[j][2] -= arr[j + 1][2];
}
}
}
}
int main(){
int cnt;
int atv[1000][3], maxVal[1000][2];//start,finish,value|val,finish
while (scanf("%d", &cnt)){
for (int i = 0; i < cnt; i++){
scanf("%d%d%d", &atv[i][0], &atv[i][1], &atv[i][2]);
}
preDeal(atv, cnt);
for (int i = 0; i < cnt; i++){
maxVal[i][0] = atv[i][2];
maxVal[i][1] = atv[i][1];
for (int j = i; j >= 0; j--){
if (atv[i][0] >= maxVal[j][1] && maxVal[i][0] < maxVal[j][0] + atv[j][2]){
//可以接上前面的活动&&当前所有活动最大价值<前面所有活动最大价值 +当前活动价值
//接上活动,加上当前活动价值,更新最大价值结束点为当前活动结束点
maxVal[i][0] = maxVal[j][0] + atv[j][2];
maxVal[i][1] = atv[i][1];
break;
}
else if (atv[i][0] < maxVal[j][1] && maxVal[i][0] < maxVal[j][0]){
//不能接上前面活动&&当前活动最大价值<前面活动最大价值
//更新当前活动最大价值为前面活动的最大价值,
maxVal[i][0] = maxVal[j][0];
maxVal[i][1] = maxVal[j][1];
}
}
}
printf("%d,%d", maxVal[cnt - 1][0], maxVal[cnt - 1][1]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息