2022华为软件挑战赛流量管理

1.题目描述

  1. 共有 M 个客户节点和 N 个边缘节点。
  2. 在每个时刻,要决策如何把每个客户节点的带宽需求分配到边缘节点。
  3. 为了确保调度质量,每个客户节点的需求只能分配到满足 QoS 约束的边缘节点
    上。即:当客户节点和边缘节点之间的 QoS 小于“QoS 上限”时,才会进行流量
    分配。
  4. 在每个时刻,每个边缘节点接收的带宽需求总和不能超过其带宽上限。
  5. 合理分配所有时刻的客户节点带宽需求,使得最终的带宽总成本尽量小。
  6. 成本为某个边缘节点,统计它在每个时刻分配的带宽之和,这些值
    在整个时间线上形成一个带宽序列,对其进行升序排序,以其 95%位置(向上
    取整)的带宽值作为该节点的 95 百分位带宽。
    7.总成本为求和所有边缘节点成本得到带宽总成本。
    在这里插入图片描述
    在这里插入图片描述

2.思路

将网络节点根据连接用户数量和带宽大小进行降序排序,让一部分节点每个时刻都尽量占用带宽,一部分节点只部署5%个时刻的带宽,这些节点的成本即为0。
在这里插入图片描述
如图,竖条为所有网络节点在所有时刻的带宽部署情况,横条为95%时刻位置,前一部分的网络节点带宽最大,连接用户数量最多,在每个时刻都尽量占用,而后面的节点只占用前5%。作为前一部分节点的数量称为阈值。
最终成绩为武长赛区43名,无缘复赛,只能拿到三等奖。
在这里插入图片描述

3.代码(Java)

注释还是比较清楚的,一些细节问题可以直接看。

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Properties;

public class Main {//文件名+路径+print
	
	static int T,M,N,qos_constraint;
	static String[][] demand,qos,site_bandwidth;
	static ArrayList rear=new ArrayList();
	
	public static void main(String[] args) {
		output("");
		
        demand=new String[8929][35];//T M  [T-1][M-1]  T<=8928,N<=135,M<=35  width=430080
        site_bandwidth=new String[136][2];//N 2  [N-1][1]
        qos=new String[136][35];//N M   [N-1][M-1]   
		input();//T M N 101 11 101
		
		int gate=T-(int) Math.ceil((T-1)*0.95)-1;      //95位
		Netnode[] netnodes=new Netnode[N];//1--N-1 
		for(int i=1;i<M;i++) {
			for(int j=1;j<M;j++) {
				if(demand[0][j].equals(qos[0][i])) {
					for(int k=0;k<T;k++) {
						String t=demand[k][i];
						demand[k][i]=demand[k][j];
						demand[k][j]=t;
					}
					break;
				}
			}
		}
		for(int i=1;i<N;i++) {
			for(int j=1;j<N;j++) {
				if(site_bandwidth[j][0].equals(qos[i][0])) {
					netnodes[i]=new Netnode(Integer.parseInt(site_bandwidth[j][1]), T, M, qos[i], qos_constraint);//导入网络节点
					break;
				}
			}
			for(int j=1;j<i;j++) {
				if(netnodes[j].t<netnodes[i].t) {//根据网络节点的连接用户数排序;'<'或'>'需要根据数据集实际情况进行调整
					Netnode netnode=netnodes[i];
					netnodes[i]=netnodes[j];
					netnodes[j]=netnode;
				}
			}
		}
		for(int i=1;i<N;i++) {
			for(int j=i+1;j<N;j++) {
				if(netnodes[i].t==netnodes[j].t) {
					if(netnodes[i].width<netnodes[j].width) {//连接用户数相同在根据总带宽排序;'<'或'>'需要根据数据集实际情况进行调整
						Netnode netnode=netnodes[i];
						netnodes[i]=netnodes[j];
						netnodes[j]=netnode;
					}
				}else {
					break;
				}
			}
		}
		int threshold=getthreshold(netnodes);  //阈值,阈值前面的网络节点尽量塞满,后面的只塞5%
		for(int i=threshold;i<N;i++) {
			for(int j=i+1;j<N;j++) {
				if(netnodes[i].t>netnodes[j].t) {//对阈值后面的节点根据网络节点的连接用户数排序;'<'或'>'需要根据数据集实际情况进行调整,记得和函数getthreshold里这部分同号
					Netnode netnode=netnodes[i];
					netnodes[i]=netnodes[j];
					netnodes[j]=netnode;
				}
			}
		}
		for(int i=threshold;i<N;i++) {
			for(int j=i+1;j<N;j++) {
				if(netnodes[i].t==netnodes[j].t) {
					if(netnodes[i].width>netnodes[j].width) {//连接用户数相同在根据总带宽排序;'<'或'>'需要根据数据集实际情况进行调整,记得和函数getthreshold里这部分同号
						Netnode netnode=netnodes[i];
						netnodes[i]=netnodes[j];
						netnodes[j]=netnode;
					}
				}else {
					break;
				}
			}
		}
		for(int i=1;i<T;i++) {
			for(int j=1;j<M;j++) {
				output(distribute(i, j, threshold, netnodes)+"\n");//进行模拟
			}
			for(int j=1;j<N;j++) {
				netnodes[j].twidth=netnodes[j].width;//更新本轮带宽
			}
			for(int j=0;j<rear.size();j++) {
				netnodes[(int) rear.get(j)].gate--;
			}
			rear.clear();
		}
		print(netnodes);//remove
	}
	public static int getthreshold(Netnode[] tnetnodes) {//测试最佳阈值
		int threshold=0,cost=500000000;
		Netnode[] netnodes=new Netnode[N];
		for(int m=1;m<N;m++) {            //测试最佳阈值
			for(int i=1;i<N;i++) {
				netnodes[i]=tnetnodes[i];
			}
			for(int i=m;i<N;i++) {
				for(int j=i+1;j<N;j++) {
					if(netnodes[i].t>netnodes[j].t) {//根据网络节点的连接用户数排序;'<'或'>'需要根据数据集实际情况进行调整
						Netnode netnode=netnodes[i];
						netnodes[i]=netnodes[j];
						netnodes[j]=netnode;
					}
				}
			}
			for(int i=m;i<N;i++) {
				for(int j=i+1;j<N;j++) {
					if(netnodes[i].t==netnodes[j].t) {
						if(netnodes[i].width>netnodes[j].width) {//对阈值后面的节点排序;'<'或'>'需要根据数据集实际情况进行调整
							Netnode netnode=netnodes[i];
							netnodes[i]=netnodes[j];
							netnodes[j]=netnode;
						}
					}else {
						break;
					}
				}
			}
			for(int i=1;i<T;i++) {
				for(int j=1;j<M;j++) {
					distribute(i, j, m, netnodes);
				}
				for(int j=1;j<N;j++) {
					netnodes[j].twidth=netnodes[j].width;
				}
				for(int j=0;j<rear.size();j++) {
					netnodes[(int) rear.get(j)].gate--;
				}
				rear.clear();
			}
			int sum=0;
			for(int i=1;i<N;i++) {
				Arrays.sort(netnodes[i].widtharray);
				sum+=netnodes[i].widtharray[(int)Math.ceil((T-1)*0.95-1)];
			}
			if(cost>sum) {
				cost=sum;
				threshold=m;
			}
			for(int j=1;j<N;j++) {
				for(int k=1;k<T;k++) {
					netnodes[j].widtharray[k-1]=0;
					netnodes[j].gate=T-(int) Math.ceil((T-1)*0.95)-1;
				}
			}
		}
		return threshold;
	}
	public static String distribute(int i,int j,int threshold,Netnode[] netnodes) {//分配算法
		int need=Integer.parseInt(demand[i][j]);
		String ts=demand[0][j]+":";
		if(need==0) {
			return ts;
		}
		for(int k=1;k<N;k++) {
			if(netnodes[k].qos[j]<qos_constraint&&netnodes[k].twidth>0) {//判断用户能否接上该节点
				if(k<threshold) {//N/4-(15-20)   //判断该用户节点进去阈值前段还是阈值后段
					if(need>netnodes[k].twidth) {
						need-=netnodes[k].twidth;
						netnodes[k].widtharray[i-1]=netnodes[k].width;
						ts+="<"+netnodes[k].id+","+netnodes[k].twidth+">,";
						netnodes[k].twidth=0;
					}else if(need<=netnodes[k].twidth){
						netnodes[k].twidth-=need;
						netnodes[k].widtharray[i-1]+=need;
						ts+="<"+netnodes[k].id+","+need+">";
						need=0;
						break;
					}
				}else {
					if(netnodes[k].gate>0) {         //判断阈值后端的节点是否还有位置(5%)
						if(need>netnodes[k].twidth) {
							need-=netnodes[k].twidth;
							netnodes[k].widtharray[i-1]=netnodes[k].width;
							ts+="<"+netnodes[k].id+","+netnodes[k].twidth+">,";
							netnodes[k].twidth=0;
							netnodes[k].gate--;
							if(rear.contains(k)) {
								rear.remove(rear.indexOf(k));
							}
						}else if(need<=netnodes[k].twidth){
							netnodes[k].twidth-=need;
							netnodes[k].widtharray[i-1]+=need;
							ts+="<"+netnodes[k].id+","+need+">";
							need=0;
							if(!rear.contains(k)) {
								rear.add(k);
							}
							//netnodes[k].gate--;
							break;
						}
					}
				}
			}
		}
		if(need!=0) {      //判断该用户节点的需求是否已经分配完
			for(int k=threshold;k<N;k++) {
				if(netnodes[k].qos[j]<qos_constraint&&netnodes[k].twidth>0) {
					if(need>netnodes[k].twidth) {
						need-=netnodes[k].twidth;
						netnodes[k].widtharray[i-1]=netnodes[k].width;
						ts+="<"+netnodes[k].id+","+netnodes[k].twidth+">,";
						netnodes[k].twidth=0;
					}else if(need<=netnodes[k].twidth){
						netnodes[k].twidth-=need;
						netnodes[k].widtharray[i-1]+=need;
						ts+="<"+netnodes[k].id+","+need+">";
						need=0;
						break;
					}
				}
			}
		}
		return ts;
	}
	public static void print(Netnode[] netnodes) {//打印结果
		int sum1=0;
		for(int i=1;i<N;i++) {
			Arrays.sort(netnodes[i].widtharray);
			//System.out.println(i+":"+Arrays.toString(netnodes[i].widtharray));
			output(i+":"+Arrays.toString(netnodes[i].widtharray)+"\n\n");
			sum1+=netnodes[i].widtharray[(int)Math.ceil((T-1)*0.95-1)];
		}
		System.out.println(sum1);
	}
	public static void input(){//输入
		String line = "";
        String tarray[];
        int i=0,j=0;
        try (BufferedReader br = new BufferedReader(new FileReader("D:\\华为软件挑战赛\\线下调试数据\\data1\\demand.csv"))) {//"/data/demand.csv"
        	while ((line = br.readLine()) != null) {
                tarray = line.split(",");
                for(j=0;j<tarray.length;j++) {
                	demand[i][j]=tarray[j];
                }
                i++;
            }
    		T=i--;
    		M=j--;
        } catch (IOException e) {
            e.printStackTrace();
        }
        i=0;
        try (BufferedReader br = new BufferedReader(new FileReader("D:\\华为软件挑战赛\\线下调试数据\\data1\\site_bandwidth.csv"))) {//"/data/site_bandwidth.csv"
        	while ((line = br.readLine()) != null) {
                tarray = line.split(",");
                for(j=0;j<tarray.length;j++) {
                	site_bandwidth[i][j]=tarray[j];
                }
                i++;
            }
    		N=i--;
        } catch (IOException e) {
            e.printStackTrace();
        }
        i=0;
        try (BufferedReader br = new BufferedReader(new FileReader("D:\\华为软件挑战赛\\线下调试数据\\data1\\qos.csv"))) {//"/data/qos.csv"
        	while ((line = br.readLine()) != null) {
                tarray = line.split(",");
                for(j=0;j<tarray.length;j++) {
                	qos[i][j]=tarray[j];
                }
                i++;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        
		try {
			FileInputStream fin;
			fin = new FileInputStream("D:\\华为软件挑战赛\\线下调试数据\\data1\\config.ini");//"/data/config.ini"
			Properties props=new Properties();
			props.load(fin);
			qos_constraint=Integer.parseInt(props.getProperty("qos_constraint"));
			fin.close(); 
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	public static void output(String result) {//输出
		String path="D:\\华为软件挑战赛\\线下调试数据\\data1\\output\\solution.txt";//"/output/solution.txt"
		FileWriter fwriter = null;
        try {
        	if(!result.equals("")) {
        		fwriter = new FileWriter(path, true);
                fwriter.write(result);
        	}else {
        		fwriter = new FileWriter(path);
                fwriter.write(result);
        	}
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            try {
                fwriter.flush();
                fwriter.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
	}
}
class Netnode{                    //网络节点类
	public int width,twidth,t,gate;
	public int[] qos,widtharray;//qos:1--m-1
	String id;
	public Netnode(int width,int T,int M,String[] d,int qc){
		this.width=width;
		twidth=width;
		widtharray=new int[T-1];
		gate=T-(int) Math.ceil((T-1)*0.95)-1;
		qos=new int[M];
		id=d[0];
		for(int i=1;i<M;i++) {
			qos[i]=Integer.parseInt(d[i]);
			if(qos[i]<qc) {
				t++;
			}
		}
	}
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值