放置阶段我用动态规划算法,java源码如下:

import java.util.ArrayList;
/**输入:服务器规格、虚拟机规格及预测数目、要优化资源维度
* 输出:放置结果和预测结果,以给定字符串形式返回
* @author wenj16
*/
public class DP {
/**输入参数
* bag 服务器类
* predictEcs 预测的虚拟机规格和数目,已经被处理成一个列表
* optResource 需要优化的资源维度,有CPU和MEM
*/
Bag bag;
ArrayList<Ecs> predictEcs;
String optResource;
/**中间变量和输出参数
* 注意:题目要求的是返回一个字符串数组
* c 动态规划每个点的最优值
* em 动态规划每个点消耗的内存
* record 记录每个点的上一个点
* cpu 动态规划每个点消耗的cpu,c、em、cpu可能编的有点多余,但是不影响
* x 记录每个物品是否被装进背包
* bagNum 开的背包个数
* secResult 返回第二阶段结果,是一个数列,每个元素存放一个背包装载情况
* totalNum 第一阶段虚拟机总预测数
* finalRes 最终结果
*/
int[][] c;
int[][] em;
int[][] record;
int[][] cpu;
int[] x;
int bagNum;
int totalNum;
ArrayList<String> secResult = new ArrayList<String>();
String[] finalRes;
/**我用一个一维数组backup备份预测阶段各个虚拟机的数目,用于修改第一阶段的预测结果
*
*/
int[] backup;
DP(ArrayList<Ecs> predictInfo,String optResource,Bag bag){
this.predictEcs=predictInfo;
this.optResource=optResource;
this.bag=bag;
}
/**动态规划解这个背包问题
* 可能会开若干个非常大的数组,用来迭代计算,内存占用比较大,要想办法优化
*/
public void init() {
//备份虚拟机预测数目到backup数组
backup=new int[predictEcs.size()];
for(int i=0;i<backup.length;i++) {
backup[i]=predictEcs.get(i).num;
}
//将内存统一除以1024
for(int i=0;i<predictEcs.size();i++) {
predictEcs.get(i).eme/=1024;
}
//计算背包cpu
int maxCPU= bag.cpuCap;
//计算背包内存
int maxEM=bag.emeCap ;
//-------------------------------------------_-_--------------------优化cpu-------------------------------
if(this.optResource.equalsIgnoreCase("CPU")) {
//要优化资源维度是cpu
boolean flag=true;
while(flag==true) {
flag=false;
//动态规划
//计算预测的虚拟机数目
int goodNum=0;
for(int i=0;i<predictEcs.size();i++) {
goodNum+=predictEcs.get(i).num;
}
//初始化矩阵
c=new int[goodNum+1][maxCPU+1];
em=new int[goodNum+1][maxCPU+1];
//记录上一个点
record=new int[goodNum+1][maxCPU+1];
//依次遍历每个虚拟机
for(int i=1;i<=goodNum;i++) {
//计算i属于第几个flavor
int type=0;
int sum=0;
for(int j=0;j<predictEcs.size();j++) {
sum+=predictEcs.get(j).num;
if(i<=sum) {
type=j;//j=0 属于flavor1
break;
}
}
//依次遍历每个cpu
for(int j=1;j<=maxCPU;j++) {
//状态转移方程
if(predictEcs.get(type).cpu <= j) {//背包可能装下j
if(predictEcs.get(type).cpu +c[i-1][j - predictEcs.get(type).cpu] > c[i-1][j]) {//装下价值更大
if(predictEcs.get(type).eme + em[i-1][j - predictEcs.get(type).cpu] <= maxEM) {//内存也不违背
c[i][j] = predictEcs.get(type).cpu + c[i-1][j - predictEcs.get(type).cpu];
em[i][j] = predictEcs.get(type).eme + em[i-1][j - predictEcs.get(type).cpu];
record[i][j]=j - predictEcs.get(type).cpu;
}else if(predictEcs.get(type).eme + em[i-1][j - predictEcs.get(type).cpu] > maxEM) {//能够装下但是内存会违背
c[i][j] = c[i-1][j];
em[i][j] = em[i-1][j];
record[i][j]=j;
for(int k=j-1;k>=0;k--) {//遍历看上一步哪个点内存不违背而且价值更大
if(em[i-1][k]+predictEcs.get(type).eme<=maxEM && c[i-1][k]+predictEcs.get(type).cpu>c[i-1][j]) {
c[i][j]=c[i-1][k]+predictEcs.get(type).cpu;
em[i][j]=em[i-1][k]+predictEcs.get(type).eme;
record[i][j]=k;//记录下这个位置
break;
}
}
}
}
else {
c[i][j] = c[i-1][j];
em[i][j] = em[i-1][j];
record[i][j]=j;
}
}else {
c[i][j] = c[i-1][j];
em[i][j] = em[i-1][j];
record[i][j]=j;
}
}
}
//反向逆推获得背包物品
boolean[] x = new boolean[goodNum+1];
int cpuTemp=maxCPU;
for(int i=goodNum;i>0;i--) {
if(record[i][cpuTemp]==cpuTemp)
x[i]=false;
else {
x[i]=true;
//计算i属于第几个flavor
int type=0;
int sum=0;
for(int j=0;j<predictEcs.size();j++) {
sum+=predictEcs.get(j).num;
if(i<=sum) {
type=j;
break;
}
}
cpuTemp=record[i][cpuTemp];
}
}
//返回一个背包装载结果
String oneBagResult = "";
int[] flavorNums=new int[predictEcs.size()];
int index=1;
for(int i=0;i<predictEcs.size();i++) {
int temp =predictEcs.get(i).num;
if(temp!=0) {
int total=0;
for(int j=index;j<index+temp;j++) {
if(x[j]==true) {
total+=1;
//资源扣减
predictEcs.get(i).num--;
}
}
index+=temp;
if(total!=0) {
oneBagResult = oneBagResult + predictEcs.get(i).name + " " + total + " ";//flavor1 1 flavor2 0 flavor3 0
flavorNums[i]=total;
}
}
}
//将背包放入列表
secResult.add(oneBagResult);
bagNum++;
//判断剩下资源有足够一个背包的资源,有就再开一个
boolean flag2=true;
while(flag2==true) {
for(int i=0;i<predictEcs.size();i++) {
if(predictEcs.get(i).num<flavorNums[i]) {
flag2=false;
break;
}
}
if(flag2==true) {
secResult.add(new String(oneBagResult));
bagNum++;
for(int i=0;i<predictEcs.size();i++) {
predictEcs.get(i).num-=flavorNums[i];
}
}
}
/**计算背包资源总数,如果小于一个背包的15%,修改备份backup中的预测数,同时将所有虚拟机设置为0
* 同时还得重新计算预测虚拟机总数
*/
double restResources=0;
for(int i=0;i<predictEcs.size();i++) {
restResources=restResources+predictEcs.get(i).num*predictEcs.get(i).cpu;
}
if(restResources<0.15*bag.cpuCap) {
for(int i=0;i<backup.length;i++) {
backup[i]-=predictEcs.get(i).num;//修改第一阶段预测数目
predictEcs.get(i).num=0;//该虚拟机数目设置为0
}
//重新计算第一阶段虚拟机总的预测数目
totalNum=0;
for(int i=0;i<backup.length;i++) {
totalNum+=backup[i];
}
}
//下一次背包循环
for(int i= 0;i<predictEcs.size();i++) {
if(predictEcs.get(i).num!=0) {
flag=true;
break;
}
}
}
//-------------------------------------------_-_--------------------优化内存------------------------------
}else if(this.optResource.equalsIgnoreCase("MEM")) {
//计算背包内存
maxEM=bag.emeCap;
boolean flag=true;
while(flag==true) {
flag=false;
//计算预测的虚拟机数目
int goodNum=0;
for(int i=0;i<predictEcs.size();i++) {
goodNum+=predictEcs.get(i).num;
}
//初始化矩阵
c=new int[goodNum+1][maxEM+1];
cpu=new int[goodNum+1][maxEM+1];
record=new int[goodNum+1][maxEM+1];
//依次遍历每个虚拟机
for(int i=1;i<=goodNum;i++) {
//计算i属于第几个flavor
int type=0;
int sum=0;
for(int j=0;j<predictEcs.size();j++) {
sum+=predictEcs.get(j).num;
if(i<=sum) {
type=j;
break;
}
}
//依次遍历每个eme
for(int j=1;j<=maxEM;j++) {
if(predictEcs.get(type).eme <= j) {

if(predictEcs.get(type).eme +c[i-1][j - predictEcs.get(type).eme] > c[i-1][j]) {

if(predictEcs.get(type).cpu + cpu[i-1][j - predictEcs.get(type).eme] <= maxCPU) {
c[i][j] = predictEcs.get(type).eme + c[i-1][j - predictEcs.get(type).eme ];
cpu[i][j] = predictEcs.get(type).cpu + cpu[i-1][j - predictEcs.get(type).eme];
record[i][j]=j - predictEcs.get(type).eme;

}else if(predictEcs.get(type).cpu + cpu[i-1][j - predictEcs.get(type).eme] > maxCPU) {
c[i][j] = c[i-1][j];
cpu[i][j] = cpu[i-1][j];
record[i][j]=j;
for(int k=j-1;k>=0;k--) {
if(cpu[i-1][k]+predictEcs.get(type).cpu<=maxCPU && c[i-1][k]+predictEcs.get(type).eme>c[i-1][j]) {
c[i][j]=c[i-1][k]+predictEcs.get(type).eme;
cpu[i][j]=cpu[i-1][k]+predictEcs.get(type).cpu;
record[i][j]=k;
break;
}
}
}
}

else {
c[i][j] = c[i-1][j];
cpu[i][j] = cpu[i-1][j];
record[i][j]=j;
}

}else {
c[i][j] = c[i-1][j];
cpu[i][j] = cpu[i-1][j];
record[i][j]=j;
}
}

}
//反向逆推获得背包物品
boolean[] x = new boolean[goodNum+1];
int emeTemp=maxEM;
for(int i=goodNum;i>0;i--) {
if(record[i][emeTemp]==emeTemp)//bug鍦ㄨ繖
x[i]=false;
else {
x[i]=true;
//计算i属于第几个flavor
int type=0;
int sum=0;
for(int j=0;j<predictEcs.size();j++) {
sum+=predictEcs.get(j).num;
if(i<=sum) {
type=j;
break;
}
}

emeTemp=record[i][emeTemp] ;
}
}
//返回一个背包装载结果
String oneBagResult = "";
int[] flavorNums=new int[predictEcs.size()];
int index=1;
for(int i=0;i<predictEcs.size();i++) {
int temp =predictEcs.get(i).num;
if(temp!=0) {
int total=0;
for(int j=index;j<index+temp;j++) {
if(x[j]==true) {
total+=1;
//资源扣减
predictEcs.get(i).num--;
}
}
index+=temp;
if(total!=0) {
oneBagResult = oneBagResult + predictEcs.get(i).name + " " + total + " ";
flavorNums[i]=total;
}
}
}
//将背包放入列表
secResult.add(oneBagResult);//bug 瑙e嚭涓�涓┖鑳屽寘
bagNum++;
//剩余资源是否有相同背包,有就新开同样的背包并做资源扣减
boolean flag2=true;
while(flag2==true) {
for(int i=0;i<predictEcs.size();i++) {
if(predictEcs.get(i).num<flavorNums[i]) {
flag2=false;
break;
}
}
if(flag2==true) {
secResult.add(new String(oneBagResult));
bagNum++;
for(int i=0;i<predictEcs.size();i++) {
predictEcs.get(i).num-=flavorNums[i];
}
}
}
/**计算背包资源总数,如果小于一个背包的15%,修改备份backup中的预测数,同时将所有虚拟机设置为0
* 同时还得重新计算预测虚拟机总数
*/
double restResources=0;
for(int i=0;i<predictEcs.size();i++) {
restResources=restResources+predictEcs.get(i).num*predictEcs.get(i).eme;//内存的情况单位得注意一下
}
if(restResources<0.15*bag.emeCap) {
for(int i=0;i<backup.length;i++) {
backup[i]-=predictEcs.get(i).num;//修改第一阶段预测数目
predictEcs.get(i).num=0;//该虚拟机数目设置为0
}
//重新计算第一阶段虚拟机总的预测数目
totalNum=0;
for(int i=0;i<backup.length;i++) {
totalNum+=backup[i];
}
}
//下一个背包循环
for(int i= 0;i<predictEcs.size();i++) {
if(predictEcs.get(i).num!=0) {
flag=true;
break;
}
}

}
}
System.out.println("zai看Ecses");
for(int i=0;i<predictEcs.size();i++) {
System.out.println(predictEcs.get(i).name+" "+predictEcs.get(i).cpu+" "+predictEcs.get(i).eme+" "+predictEcs.get(i).num+" ");
}
}
/**返回结果是题目要求的字符串,格式是这样的:
6
flavor5 3
flavor10 2
flavor15 1
(备注:如果某种虚拟机规格的预测结果为零,即对应写0)
4
1 flavor5 2
2 flavor5 1 flavor10 1
3 flavor15 1
4 flavor10 1
* @return 返回两阶段的结果
*/
public String[] getResult() {
int listNum=1+predictEcs.size()+1+bagNum+1;
finalRes=new String[listNum];
//第一阶段结果
finalRes[0]=""+totalNum;
for(int i=1;i<1+predictEcs.size();i++) {
finalRes[i]=predictEcs.get(i-1).name+" "+backup[i-1];
}
//第二阶段结果
finalRes[predictEcs.size()+1]=" ";
finalRes[predictEcs.size()+2]=""+bagNum;
for(int i=predictEcs.size()+3;i<listNum;i++) {
int order=i-(predictEcs.size()+3)+1;
String aBag=secResult.get(order-1);
finalRes[i]=order+" "+aBag;
}
return finalRes;
}

}

作者:wenj17

邮箱:527132554@qq.com

转载于:https://www.cnblogs.com/wenj17/p/9243237.html

2018年华为精英挑战赛初赛放置算法Java实现相关推荐

  1. 2019华为精英挑战赛初赛模拟试题总结思考

    小型机通常采用RISC和Unix操作系统 T 小型机操作系统一般是UNIX,PC服务器操作系统一般是windows.但是题干中RISC不是操作系统,是精简指令集计算机,是计算机***处理器的一种设计模 ...

  2. 华为网络精英挑战赛初赛

    华为网络精英挑战赛初赛 小型机 路由优先级 shell命令行方式 实时操作系统 传值和传引用 小型机 小型机通常采用RISC和unix操作系统. 一般认为,传统小型机是指采用RISC.MIPS等专用处 ...

  3. 2017年华为软件精英挑战赛初赛解题思路

    2017年华为软件精英挑战赛初赛解题思路 题目链接:http://codecraft.huawei.com/  常规解题思路:网络流(最小费用最大流)+ 启发式搜索算法 + 算法性能优化 1. 最大流 ...

  4. 2021华为软件精英挑战赛初赛baseline

    2021华为软件精英挑战赛初赛baseline,由ddmm大佬提供的单文件baseline按照工程开发格式改写,改为以类为单位,多文件的格式.同样没有在里面添加任何算法,相当于一个脚手架,帮助大家更快 ...

  5. 2021华为软件精英挑战赛初赛代码及思路

    2021华为软件精英挑战赛训练赛.正式赛思路分享     有幸再次参加了华为软件精英挑战赛(去年由于不知道数据集有坑,导致没能进入复赛,今年决定再来一次弥补去年的遗憾)     今年的赛题相比去年个人 ...

  6. 华为2020软件精英挑战赛初赛、复赛、决赛代码+心得分享

    目录 写在前面 初赛 第一代思路 第二代思路 最终版思路 优化思路 多线程 数据结构设计 输入和输出的优化 复赛 规则描述 优化思路 算法 多线程 数据结构设计 复赛正式赛 总决赛 总结 写在前面 2 ...

  7. 2019华为软件挑战赛初赛代码开源分享

    本项目是华为2019年软件精英挑战赛的初赛题目的实现,初赛排名西北赛区 41 名 项目地址:https://github.com/WFrame0224/SDK_python 文章目录 1. 运行说明 ...

  8. 海康威视2017软件精英挑战赛初赛题目

    题目概述 在车库中安排若干泊车机器人,根据给定的车位地图,合理优化机器人的数量及其运动路径,尽量减少客户在停车和取车中的等待时间,并使总成本最小.(试题用例包于5月初开放下载) 参数设定 为了简化问题 ...

  9. 华为软件训练营Java_华为软件精英挑战赛-如何提交打包Java代码(运行打包)

    在上一篇中我们介绍了此次大赛的环境配置,下面我们来运行我们的代码,并测试提交(Java版的,C++的小伙伴估计也差不多吧). 注意:我的Java程序是按照官网给的SDK编写,打包时,按个人情况不同做修 ...

最新文章

  1. 算法-------LIS算法(Java版本)
  2. 【PAT甲级 sc.nextInt()的使用】1008 Elevator (20 分) Java版 9/9通过
  3. SQL Server 查询性能优化——创建索引原则(一)
  4. Android 学习 笔记_03. SQLite的使用
  5. Linux中cinder的作用,cinder
  6. (转载)找工作那年,我真的哭了
  7. Sublime Text3 安装svn插件遇到的问题
  8. 计算机的基础硬件知识,计算机硬件基础知识学习_电脑硬件知识_手机硬件知识...
  9. Jenkins 系列教程-史上最简单Jenkins教程,教你一天学会使用Jenkins利器
  10. js html编码和解码,JavaScript字符集编码与解码
  11. APP加壳技术是否有效?爱加密APP加密服务有什么不同?
  12. HTTPS是如何保证数据传输安全的?
  13. java中隐函数求导法则_隐函数求导法则
  14. codeblock找不到pthread
  15. java jsr命令_Java系列:JVM指令详解(下)(zz)
  16. 通过JS代码简单实现九九乘法表
  17. nvenc vs x264 对比(2)
  18. IP公有地址和私有地址划分
  19. IP分片报文的接收与重组
  20. 可扩展标记语言XML之一:XML的概念、作用与示例

热门文章

  1. 菜鸟初学Echarts
  2. 清华姚班教授: 「读博,你真的想好了吗?」与 UIUC 王鸿伟「读博,我想好了!」...
  3. C#将秒转换为 时分秒
  4. 中国各省份名字的由来
  5. 程序员都有黑客梦,聊聊渗透工程师主要学什么?
  6. node js批量导出PDF 导出压缩为zip 拆分设计 文件压缩 批量导出设计
  7. B2B2C电商系统的价值是什么?
  8. macOS Big Sur 系统启动U盘制作教程
  9. SpringBoot国际化失败的原因,切换中英文无效
  10. 联通短消息服务器域名,中国联通域名服务器地址