问题描述
一家地区电力公司计划在未来几年内对核电站进行大规模投资。由于该地区需求不断增加以及能源危机迫使某些陈旧的化石燃料电站关闭,未来6年内必须建造8座核电站。我们假设该区域的电力需求是确定的,并且必须满足表中所示的最小累积需求水平。这里的需求已经转换为每年年底所需的对应数量的核电厂。电力公司至少要满足这一最低需求时间表。
核电站的建设大约需要一年时间。除了与电站建设直接相关的成本之外,任何电站在任何一年建造时都会产生1500万元的共同成本,与建造的电站数量无关。在任何一年中,最多可以建造3座核电站。每座电站的建造成本见下表,由于一些政策变化,每年成本也有相应变动。
年份 | 累计需求(以核电站数量计算) | 每座成本 |
---|---|---|
1 | 1 | 5400 |
2 | 2 | 5600 |
3 | 4 | 5800 |
4 | 6 | 5700 |
5 | 7 | 5500 |
6 | 8 | 5200 |
要求解的问题:将年限、最大需求量、每年的建设能力扩展为一般情况,求解电力公司n年期间成本最低的建设方案。
有以下示例,可用来验证代码的正确性
输入格式:
第一行: 6,8,3
第二行: 0 1 2 4 6 7 8
输出格式:
第一行: 48500
第二行: 3 3 0 0 2 0
问题分析
根据问题描述可知,前一阶段的决策影响到后一阶段的决策,故此题采用动态规划的算法思想比较合适。对于此题我是从后往前递推,到第1年时就可得出最优解和最优方案,然后再从第0年开始根据每年的最优建设量输出最优建设方案。
代码部分
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <time.h>
using namespace std;
#define MAX1 30
#define MAX2 50
struct optomal{
int choice[MAX2];
}V[MAX1],s[MAX1];
//为了在下面的返回多个值
struct return_value{
int a;
int b;
int z;
};
//数组t表示每年的建造成本,数组V表示每年可能情形下的最优建成成本
//数组s表示每年的可能的最优解情况
//数组c表示在当年年底应建成的核电厂的累计数量
int t[MAX1],c[MAX1];
void Print(int n){
printf("\n最优成本为:%d\n",V[1].choice[0]);
printf("======================最优方案为:======================\n");
int x;
for(int j=1;j<=n;j++){
if(j==1){
printf("第1年建造%d台核电站\n",s[j].choice[0]);
x=s[j].choice[0];
}
else{
printf("第%d年建造%d台核电站\n",j,s[j].choice[x]);
x+=s[j].choice[x];
}
}
}
void Judgment(int temp,int y,int min,int i,int co){
for(int j=0;j<=co;j++){
if((temp+j)<c[i])
continue;
else{
if(y==1){
if(j==0){
V[i].choice[temp]=V[i+1].choice[temp];
s[i].choice[temp]=j;
y--;
continue;
}
else{
V[i].choice[temp]=V[i+1].choice[temp+j]+t[i]*j+1500;
s[i].choice[temp]=j;
y--;
continue;
}
}
min=V[i+1].choice[temp+j]+t[i]*j+1500;
if(min<V[i].choice[temp]){
V[i].choice[temp]=min;
s[i].choice[temp]=j;
}
}
}
}
struct return_value RandomGenerated(){
int n,m,limit;
//随机生成定量条件的部分
srand(time(NULL));
//手动输入每年的建造能力上限
//scanf("%d",&limit);
//随机生成每年的建造能力上限
limit=3+rand()%3;
n=20+rand()%10;
printf("每年年底最少应建成的核电站数量:");
for(int i=0;i<=n;i++){
if(i==0){
c[i]=0;
printf("%3d",c[i]);
}
if(i>0){
c[i]=c[i-1]+1+rand()%3;
printf("%3d",c[i]);
}
}
m=c[n];
printf("\n建造年限、要建成的数量和每年的建造能力上限分别为:");
printf("%d,%d,%d\n",n,m,limit);
printf("每年的建造成本分别为:");
for(int i=1;i<=n;i++){
t[i]=rand()%1000+5000;
printf("%5d",t[i]);
}
printf("\n");
struct return_value value_stu;
value_stu.a=n;
value_stu.b=m;
value_stu.z =limit;
return value_stu;
}
void NpowerArrange(int n,int m,int limit){
int temp,i;
for(i=n;i>=1;i--){
if(i==n) V[i+1].choice[m]=0;
temp=c[i-1];
if((i-1)*limit>=m){
for(;temp<=m;temp++){//temp每年开始的所有可能的核电站总数
if(m-temp>=limit){
int m1,y=1,j=0;
Judgment(temp,y,m1,i,limit);
}
else{
int m2,y=1,j=0;
Judgment(temp,y,m2,i,m-temp);
}
printf("%-7d",V[i].choice[temp]);
}
}
if((i-1)*limit<m){
for(;temp<=(i-1)*limit;temp++){//temp每年开始的所有可能的核电站总数
if(m-temp>=limit){
int m1,y=1,j=0;
Judgment(temp,y,m1,i,limit);
}
else{
int m2,y=1,j=0;
Judgment(temp,y,m2,i,m-temp);
}
printf("%-7d",V[i].choice[temp]);
}
}
printf("\n");
}
if(i==0) Print(n);
}
int main(){
int n,m,limit;
//随机验证部分
struct return_value stu_main;
stu_main=RandomGenerated();
n=stu_main.a;m=stu_main.b;limit=stu_main.z;
//检验算法正确的部分
// printf("请分别输入建造年限、要建成的数量和每年的建造能力上限:");
// scanf("%d,%d,%d",&n,&m,&limit);
// printf("请输入每年年底最少应建成的核电站数量:");
// printf("请输入每年年底最少应建成的核电站数量:");
// for(int i=0;i<=n;i++){
// scanf("%d",&c[i]);
// }
// printf("每年的建造成本分别为:");
// for(int i=1;i<=n;i++){
// scanf("%d",&t[i]);
// }
NpowerArrange(n,m,limit);
return 0;
}
代码的运行截图
验证题目中所给的示例
随机验证
————————————————
版权声明:本文为CSDN博主「JiQiaoqiao1212」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/JiQiaoqiao1212/article/details/107145127