标签:
某公司针对某项目进行为期五年的规划,该项目使用某种设备,该公司有一台已经使用了两年的该型设备。每年年初该公司都有两种选择,一是更新设备,二是继续使用。设备在使用过程中会产生维修费用。设备更新、维修费用由下表给出,求解该公司如何更新设备可以获得最大利润。
在规划之前,先引入几个符号。
表示第i年初的设备是第t年买得话,所做的策略,true表示更新,false表示继续使用。
应用动态规划的方法,我们可以采用逆序求解的方式,从第五年年初设备状态开始求取,并且我们第五年年底,无论设备状态如何,第六年利润都为0。
首先,我们来推导利润的求解。
假设在第i年年初,拥有的设备是第t年买的。这时,我们有两个选择,更新当前设备,或者继续使用当前设备。
对于第五年年初,我们的设备状态可能有五种:第0年的设备,第一年的设备,第二年的设备,第三年的设备,第四年的设备。
对于每一种状态,若求得结果时,选择更新的利润大,置为true,否则置为false。
照此方法,对于第一年年初,设备状态只有一种:第0年的设备。
更新的利润为32,继续使用的话是50,因此第一步我们要选择继续使用。
此时,我们再反过来查看每一步的选择。第一步我们选择了继续使用,第二步的状态就是使用第0年的设备,更新利润为36,继续为37,因此选择继续使用;第三步初始状态也为使用第0年设备,更新利润为27,继续使用为21,因此选择更新;第四步初始状态为使用第三年设备,继续使用为18,更新为13,选择继续使用;第五步初始状态为使用第三年设备,继续使用为14,更新为-4,因此为继续使用。
基于此,我们得到了最优的更新策略,第一年第二年不更新,第三年更新,第四年第五年不更新,最大利润为50。
/* 算法设计与分析作业 ---设备最优更新策略 */ #include<iostream> void accept(int **a, int years); int max(int a, int b) { return a > b ? a : b; } int main() { using std::cin; using std::cout; using std::endl; cout << "请输入决策年数(i):" << endl; int temp; while (!(cin >> temp)||temp < 0) { cout << "请输入一个正整数:" << endl; cin.clear(); while (cin.get() != ‘\n‘); } int years = temp + 1; //第i年买的设备在第t年能产生的利润 int **exProfit = new int*[years];//0-n年买的设备 for (int i = 0; i < years; i++) { exProfit[i] = new int[years];//0-n年买的设备在第i年的利润 } cout << "请依次输入利润:" << endl; accept(exProfit, years); //第i年买的设备在第t年产生的维修费用 int **fix = new int *[years]; for (int i = 0; i < years; i++){ fix[i] = new int[years]; } cout << "请依次输入维修费用:" << endl; accept(fix, years); //第i年买的设备在第t年更新时的费用 int **update = new int *[years]; for (int i = 0; i < years; i++){ update[i] = new int[years]; } cout << "请依次输入更新费用:" << endl; accept(update, years); //最优更新策略,true代表更新,false代表继续使用 bool **choice = new bool *[years]; for (int i = 0; i < years; i++) { choice[i] = new bool[years]; } for (int i = 0; i < years; i++){ for (int j = 0; j < years; j++) choice[i][j] = false; } //最终利润,决策年数之后的一年利润全部置0 int **profit = new int*[years]; for (int i = 0; i < years; i++) { profit[i] = new int[years + 1]; } for (int i = 0; i < years; i++) { for (int j = 0; j < years + 1; j++) profit[i][j] = 0; } //倒序进行计算,第i年,可以使用的设备要么就是之前一直没更新,要么就是第j年买的设备 //例如,第三年,设备的状态就有三种选择,一是使用第0年的设备,二是在第一年进行了更新,三是第二年进行了更新 //分别对每个状态进行选择更新或者继续使用 //第i年,有两种选择,要么更新,要么继续使用 //分别计算更新和继续使用的利润,选择两者中比较大的。 for (int i = temp; i >0 ; i--) { for (int j = 0; j < i; j++) { int keep = exProfit[j][i] - fix[j][i] + profit[j][i + 1]; int refresh = exProfit[i][i] - fix[i][i] - update[j][i] + profit[i][i + 1]; profit[j][i] = max(keep, refresh); if (keep < refresh) { choice[i][j] = true; } } } int j = 0; for (int i = 1; i < years; i++) { if (choice[i][j]) { j = i; std::cout <<"第"<<i<< "年更新"<<std::endl; continue; } std::cout << "第" << i << "年继续使用" << std::endl; } cout << "利润最大为:" << profit[0][1]; delete[]profit; for (int i = 0; i < years; i++) { delete[] fix[i]; } delete[]fix; for (int i = 0; i < years; i++) { delete[] exProfit[i]; } delete[]exProfit; for (int i = 0; i < years; i++) { delete[] update[i]; } delete[]update; for (int i = 0; i < years; i++) { delete[] choice[i]; } delete[]choice; } void accept(int **a ,int years) { for (int i = 0; i < years; i++) { std::cout << "第"<<i<<"年:"; int j = 0; a[i][j] = 0; j++; while (j < years) { if (j < i) a[i][j] = 0; else { while (!(std::cin >> a[i][j])||a[i][j] < 0) { if(i == 0) std::cout << "请从第" <<j<<"个数重新输入"<< std::endl; else std::cout << "请从第" << j-i+1 << "个数重新输入" << std::endl; std::cout << "请输入正整数"; std::cin.clear(); while (std::cin.get() != ‘\n‘); } } j++; } } }
标签:
原文地址:http://www.cnblogs.com/aguoshaofang/p/5012751.html