之所以学习算法,并不是单纯为了练脑子(笑),更多的时候是实现复杂而不同的需求。
在电气专业中,供电是有高峰和低峰的,根据数据情况确定用电高峰和用电低峰从而按需供电,是非常有必要的。
这个程序解决的问题,原型来自于2018年电工杯数学建模,至于模型的建立,并不是我这个码农的事情了(哈),这个c++程序是提供数据信息的。
算法要求和分析:
1.有100个电动汽车,会在不同的时间进行充电,充电会延续一段时间,不同的电动汽车消耗的功率是不同的。
2.配电是根据这100个电动汽车用电状况进行配电的,由于电动汽车互相不干扰,所以可能产生多辆汽车同时用电的状况。
3.电动汽车的电池有共同的特性,在连续充电的过程中,前五分钟是不充电的,到了 75分钟之后充电也会停止
4.不同的日期不同的电动汽车的充电功率是不同的
算法模型介绍:
1.将一天的时间每十五分钟为一段分为96段,计算每一段消耗的能量。
2.将每一段时间所有电动汽车使用电量的叠加作为这个时间段的总用电量,根据总用电量的变化确定供电曲线。
3.采用文件输入的方式,将文件中时间点的小时和分钟进行离散储存,采用静态链表的方式进行储存处理数据。
Main.cpp
#include<fstream> // 文件流 #include<iostream> // 标准流 #include<string> // 字符串 #include <sstream> #include "Read.h" using namespace std; // 使用std名字空间 int main() { Readfile Rd; int j; //输出使用 int num=0; int ho,mi; double h,p; ifstream inFile; ofstream Battery_out; inFile.open("Wednesday.txt"); // 打开文件 Battery_out.open("Wednesday_out.txt", std::ios::out | std::ios::app); string str; // 字符串 double a[4]; int i=0; // 列 if(inFile.is_open()) { // 若成功打开文件 while(!inFile.eof()) { // 若未到文件结束 i=0; getline(inFile, str, ‘\n‘); // 读取一行内容,存入存str中 istringstream istr(str); while( !istr.eof() ) { istr >> a[i]; i++; } ho=a[0]; //数据读入 mi=a[1]; h=a[2]; p=a[3]; Rd.Initial(ho,mi,h,p,num); Rd.Increase(num); num++; } } inFile.close(); // 关闭文件 for (i=0;i<100;i++) { Battery_out<<endl; for (j=0;j<96;j++) { double temp=Rd.Result(i,j); Battery_out<<temp<<‘ ‘; } } Battery_out.close(); }
Read.h
#include <iostream> using namespace std; struct Read { int hour; int minute; int time; double P; }; class Readfile { private: Read R[100]; double Battery[100][96]; public: Readfile(); ~Readfile(); void Initial(int ho,int mi,double h,double p,int num); int Transform(double h); void Increase(int num); double Result(int i,int j); };
Read.cpp
#include <iostream> #include "Read.h" using namespace std; Readfile::Readfile() //设置电池所有数字为0 { int i,j; for (i=0;i<100;i++) for (j=0;j<96;j++) Battery[i][j]=0; } Readfile::~Readfile() {} int Readfile::Transform(double h) //将小时转化为分钟 { int minute=60*h; return minute; } void Readfile::Initial(int ho,int mi,double h,double p,int num) //读入数据 { R[num].hour=ho; R[num].minute=mi; R[num].time=Transform(h); R[num].P=p; } void Readfile::Increase(int num) { if (R[num].time>75) R[num].time=75; if (R[num].time<5) return; //充电不足五分钟,退出 else if (R[num].time>5&&(R[num].time<15-R[num].minute%15||R[num].time==15-R[num].minute%15)) //充电大于五分钟,而且充电时间小于等于第一个时间段剩余时间 { int j=R[num].hour*4+R[num].minute/15; //计算时间段标号 double ba=(R[num].time-5)*R[num].P; //计算功率(不计五分钟) Battery[num][j]=ba; //记录能量 return; } else { if ((15-R[num].minute%15)>5) //充电时间大于五分钟,充电时间溢出第一个时间段,第一个时间段剩余时间大于5分钟 { int j=R[num].hour*4+R[num].minute/15; //计算时间段标号 double ba=(15-R[num].minute%15-5)*R[num].P; //计算当前段功率(不计五分钟) Battery[num][j]=ba; //记录能量 R[num].time-=(15-R[num].minute%15); //时间减少 R[num].minute+=15-R[num].minute%15; //分钟时刻增加 if (R[num].minute>=60) //分钟满60进位 { R[num].minute-=60; R[num].hour++; if (R[num].hour>=24) //小时大于24结束 return; } } else //充电时间大于五分钟,充电时间溢出第一个时间段,第一个时间段剩余时间小于五分钟 { int temp=5-(15-R[num].minute%15); //第一个五分钟消耗剩余时间 R[num].time-=(15-R[num].minute%15); //时间减少 R[num].minute+=15-R[num].minute%15; //分钟时刻增加 if (R[num].minute>=60) //分钟满60进位 { R[num].minute-=60; R[num].hour++; if (R[num].hour>=24) //小时大于24结束 return; } int j=R[num].hour*4+R[num].minute/15; //计算时间段标号 double ba=(15-temp)*R[num].P; //计算当前段功率(不计temp) Battery[num][j]=ba; //记录能量 R[num].time-=15; //时间减少 R[num].minute+=15; //分钟时刻增加 if (R[num].minute>=60) //分钟满60进位 { R[num].minute-=60; R[num].hour++; if (R[num].hour>=24) //小时大于24结束 return; } } } while (R[num].time-15>0) { int j=R[num].hour*4+R[num].minute/15; //计算时间段标号 double ba=15*R[num].P; //计算当前段功率 Battery[num][j]=ba; //记录能量 R[num].time-=15; //时间减少 R[num].minute+=15; //分钟时刻增加 if (R[num].minute>=60) //分钟满60进位 { R[num].minute-=60; R[num].hour++; if (R[num].hour>=24) //小时大于24结束 return; } } int j=R[num].hour*4+R[num].minute/15; //计算时间段标号 double ba=R[num].time*R[num].P; //计算当前段功率 Battery[num][j]=ba; //记录能量 } double Readfile::Result(int i,int j) //输出 { return Battery[i][j]; }
Increase代码分析:
我说Increase函数是这个算法最精华的部分,绝对不为过。
前五分钟不冲电以及开始时间点并不为整点这两个问题是最难处理的
前五分钟不冲电无疑会减少某些时间段电池的损耗,同样的,开时间点不为整点也是同一个道理。
因此我将情况分为以下几种情况:
1.充电时间小于五分钟
2.充电时间大于五分钟,且充电时间段小于第一个时间段剩余时间
3.充电时间大于五分钟,充电时间溢出第一个时间段,第一个时间段剩余时间大于五分钟
4.充电时间大于五分钟,充电时间一处第一个时间段,第一个时间段剩余时间小于五分钟
2*2等于4,是否溢出第一个时间段和第一个时间段剩余时间是否大于五分钟是可以作为判别的情况的。
原文:https://www.cnblogs.com/Linda-Blog/p/9097937.html