之前我们介绍过,在一个工程中我们关心两个问题:

(1)工程是否顺利进行

(2)整个工程最短时间。

之前我们优先关心的是顶点(AOV),同样我们也可以优先关心边(同理有AOE)。(Activity On Edge Network)

看看百度百科上解释:

AOE网:Activity on edge network

若在带权的有向图中,以顶点表示事件,以有向边表示活动,边上的权值表示活动的开销(如该活动持续的时间),则此带权的有向图称为AOE网。

如果用AOE网来表示一项工程,那么,仅仅考虑各个子工程之间的优先关系还不够,更多的是关心整个工程完成的最短时间是多少;

哪些活动的延期将会影响整个工程的进度,而加速这些活动是否会提高整个工程的效率。

因此,通常在AOE网中列出完成预定工程计划所需要进行的活动,每个活动计划完成的时间,要发生哪些事件以及这些事件与活动之间的关系,

从而可以确定该项工程是否可行,估算工程完成的时间以及确定哪些活动是影响工程进度的关键。

很显然,顶点表示事件,边表示活动,边的权则表示活动持续时间。

AOE一般用来估算工程的完成时间。

AOE表示工程的流程,把没有入边的称为始点或者源点,没有出边的顶点称为终点或者汇点。一般情况下,工程只有一个开始,一个结束,

所以正常情况下,AOE只有一个源点一个汇点。

AOV和AOE的区别:

1.AOV用顶点表示活动的网,描述活动之间的制约关系。

2.AOE用边表示活动的网,边上的权值表示活动持续的时间。

AOE 是建立在子过程之间的制约关系没有矛盾的基础之上,再来分析整个过程需要的时间。

AOE研究:

a.完成整个过程至少需要多长时间。

b.哪些活动影响工程的进度?


关键路径:从源点到汇点具有最大长度的路径。这个概念要清楚,一个工程不一定有一条关键路径,可能会有多条。

关键活动:关键路径上的活动(边)。

针对上面AOE所关心的问题,要想缩短工程时间,就缩短关键路径上的过程即可。(缩短后可能出现之前的关键路径变成了非关键路径)

由于AOE网上所有的活动是可以并行进行。这里举一个例子,组装一个变形金刚,需要头,左膀右臂,身体,左腿右腿。

我们可以有两种方法:1.先做好头,做左手臂,做右手臂,做身体,做左腿,做右腿,然后再组装。

          2.同时做头、手臂、身体、腿的部分,每有一个头、两个手臂、两个腿和一个身体的时候,就可以组装了。

方法1.如我们计算机中的串行运行。这样时间开销是累加的。

方法2.如我们计算机中的并行运行。这样时间开销可以立体应用。在此方法中,同时做各个部位时间不同,比如做头时间最长,那么整个一个

变形金刚所用的时间决定与做头的时间,如果做手臂的时间是做头时间的一半,那么就是说做手臂的时间点可以在头做了一半的时候。只要不超过这个

时间点,手臂部分是不会影响整个工程的进度的。

这里定义四个定义:前两个针对顶点,后两个针对边

事件最早开始时间:顶点Vi最早发生的时间。

事件最晚开始时间:顶点Vi最晚发生的时间,超出则会延误整个工期。

活动的最早开始时间:边Eg最早发生时间。

活动的最晚开始时间:边Eg最晚发生时间。不推迟工期的最晚开工时间。

下面这个例子说明一下:

说明:上图中J中为49,是最早开始时间。这里可以看到最早开始时间,就是完要成该顶点,前面的所有到该点的路径都要已经完成。所以取路径最大那一条。

补充说明:

事件最早开始时间:例子图中,F点,ACF(9) 和 ADF(19),到达F点时候,保证AC和AD都完成,这样 F才能开始,所以F点的最早开始时间取最大值,即19.

       可以看出,要求出到某一点的最早开始时间,则需要将汇于该点的所有路径的时间求出来,取最大值。

事件最迟开始时间:这里是反着推,比如H点最迟开始时间,H到J 与 H到I到J两条路径,39 和 44,所谓最迟开始时间,就是超过这个时间就会影响整个工程进度,

         而这个时间是时间点,是从源点工程开始计时的,所以对于H点,39和44是相对于源点,如果取44,则H-J这条路径就会拖延,最迟开始时间选择最小值。

关键路径的特点:我们寻找关键路径——关键路径就是关键活动(顶点与顶点之间的边组成),就是我们怎么判断该顶点是否为关键活动(边)的顶点,即判断边是否为关键活动。

        前面定义过,关键路径就是图中从源点到汇点最长(权值最大)的路径。

        这条路径就决定了整个工程的工期,这说明一个什么问题?

        关键路径上的顶点与顶点之间的活动的应该最早开始和最迟开始时间是相等的,

        如果不等那么说明活动还有余额时间(在最早开始时间和最迟开始时间之间可以任选一个时间点开始),这说明还有其他活动是决定这个工程时间的,那就不是关键路径了。


算法思想:

要准备两个数组,a:最早开始时间数组etv,b:最迟开始时间数组。(针对顶点即事件而言)

1.从源点V0出发,令etv[0](源点)=0,按拓扑有序求其余各顶点的最早发生时间etv[i](1 ≤ i ≤ n-1)。同时按照上一章

拓扑排序的方法检测是否有环存在。

2.从汇点Vn出发,令ltv[n-1] = etv[n-1],按拓扑排序求各个其余各顶点的最迟发生时间ltv[i](n-2 ≥ i ≥ 2);

3.根据各顶点的etv和ltv数组的值,求出弧(活动)的最早开工时间和最迟开工时间,求每条弧的最早开工时间和最迟开工时间是否相等,若相等,则是关键活动。

注意:1,2 完成点(事件)的最早和最迟。3根据事件来计算活动最早和最迟,从而求的该弧(活动)是否为关键活动。


关键代码:

1.对图进行拓扑排序,存储了拓扑排序的顺序,作为关键路径的计算最迟开始时间的依据。

 int TopplogicalSort(GraphAdjList *g)
{
int count=;
eNode *e=NULL; StackType *stack=NULL;
StackType top=;
stack = (StackType *)malloc((*g).numVextexs*sizeof(StackType)); int i; //初始化拓扑序列栈
g_topOfStk = ;
//开辟拓扑序列栈对应的最早开始时间数组
g_etv = (int *)malloc((*g).numVextexs*sizeof(int));
//初始化数组
for (i=;i<(*g).numVextexs;i++)
{
g_etv[i]=;
}
//开辟拓扑序列的顶点数组栈
g_StkAfterTop = (int *)malloc(sizeof(int)*(*g).numVextexs); for (i=;i<(*g).numVextexs;i++)
{
if (!(*g).adjList[i].numIn)
{
stack[++top] = i;
// printf("init no In is %c\n",g_init_vexs[i]);
}
} while(top)
{
int geter = stack[top];
top--; //把拓扑序列保存到拓扑序列栈,为后面做准备
g_StkAfterTop[g_topOfStk++] = geter; printf("%c -> ",g_init_vexs[(*g).adjList[geter].idx]);
count++; //获取当前点出度的点,对出度的点的入度减一(当前点要出图)。
//获取当前顶点的出度点表
e = (*g).adjList[geter].fitstedge;
while(e)
{
int eIdx = e->idx;
//选取的出度点的入度减一
int crntIN = --(*g).adjList[eIdx].numIn;
if (crntIN == )
{
//如果为0,则说明该顶点没有入度了,是下一轮的输出点。
stack[++top] = eIdx;
// printf("running the vex is %c\n",g_init_vexs[e->idx]);
} //求出关键路径
if ((g_etv[geter] + e->weigh) > g_etv[eIdx])
{
g_etv[eIdx] = g_etv[geter] + e->weigh;
} e = e->next;
}
}
if (count < (*g).numVextexs)//如果图本身就是一个大环,或者图中含有环,这样有环的顶点不会进栈而被打印出来。
{
return false;
}
else
{
printf("finish\n");
return true;
} }

2.关键路径代码:

 void CriticalPath(GraphAdjList g)
{
int i;
int geter;
eNode *e = NULL;
g_topOfStk--;
//1.初始化最迟开始时间数组(汇点的最早开始时间(初值))
g_ltv = (int *)malloc(sizeof(int)*g.numVextexs);
for (i=;i<g.numVextexs;i++)
{
g_ltv[i] = g_etv[g.numVextexs-];
} //2.求每个点的最迟开始时间,从汇点到源点推。
while (g_topOfStk)
{
//获取当前出栈(反序)的序号
geter = g_StkAfterTop[g_topOfStk--];
//对每个出度点
if (g.adjList[geter].fitstedge != NULL)
{
e = g.adjList[geter].fitstedge;
while(e != NULL)
{
int eIdx = e->idx;
if (g_ltv[eIdx] - e->weigh < g_ltv[geter])
{
g_ltv[geter] = g_ltv[eIdx] - e->weigh;
}
e = e->next;
}
}
} int ete,lte;//活动最早开始和最迟开始时间 printf("start:->");
//3.求关键活动,即ltv和etv相等的
for (i=;i<g.numVextexs;i++)
{
if (g.adjList[i].fitstedge)
{
e = g.adjList[i].fitstedge;
while(e)
{
int eIdx = e->idx;
//活动(i->eIdx)最早开始时间:事件(顶点) i最早开始时间
ete = g_etv[i];
//活动(i->eIdx)最迟开始时间:事件(顶点) eIdx 最迟开始时间 减去 活动持续时间
lte = g_ltv[eIdx] - e->weigh;
if (ete == lte)
{
printf("(%c - %c)->",g_init_vexs[i],g_init_vexs[eIdx]);
}
e= e->next;
}
}
}
printf(" end\n");
}

编程所用的图:

拓扑排序结果:

过程:

1.从J开始,无后继,不做任何事情;

2.G,G的ltv为27,ltv-weight = 27-2 < 27,所以G的ltv为25;

3.I,I的ltv为27,ltv-weight = 27 -3 < 27,所以I的ltv为24;

4.H,H的ltv为24(I的ltv),24-5 < 24,所以H 的ltv为19;

依次类推。。。

完成top排序和关键路径后:

全局存放各个顶点的最早开始和最迟开始时间:

完整代码:

 // grp-top.cpp : 定义控制台应用程序的入口点。
//
// grp-top.cpp : 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include <stdlib.h> #define MAXVEX 100
#define IFY 65535 typedef char VertexType;
typedef int EdgeType;
typedef int IdxType;
typedef int QueueType;
typedef int StackType; //-------
int *g_etv = NULL;
int *g_ltv = NULL;
int *g_StkAfterTop;
int g_topOfStk; ///---------------------------------------
//边节点
typedef struct EdgeNode{
IdxType idx;
int weigh;
struct EdgeNode* next;
}eNode; //顶点节点
typedef struct VexNode{
int numIn; //入度数量
IdxType idx;
eNode *fitstedge;
}vNode; //图的集合:包含了一个顶点数组
typedef struct {
vNode adjList[MAXVEX];
int numVextexs,numEdges;
}GraphAdjList; ///-----------------------------------
/*VertexType g_init_vexs[MAXVEX] = {'A','B','C','D','E','F','G','H','I','J','K','L'}; char *g_input[] = {
"A->B->C->D",
"B->E",
"C->F->I->J",
"D->E->I->J",
"E",
"F->K",
"G->F->H->K",
"H->I",
"I->J->L",
"J->E->K",
"K->L",
"L"
};*/ ///-----------------------------------
VertexType g_init_vexs[MAXVEX] = {'A','B','C','D','E','F','G','H','I','J'}; char *g_input[] = {
"A->B->C",
"B->D->E",
"C->D->F",
"D->E",
"E->G->H",
"F->H",
"G->J",
"H->I",
"I->J",
"J",
NULL
}; char *g_input_weigh[] = {
"3,4",//A
"5,6",//B
"8,7",//C
"",//D
"9,4",//E
"",//F
"",//G
"",//H
"",//I
" ",//J
NULL
};
//===============================================================
//队列 //队列节点
typedef struct Node {
QueueType data;
struct Node *next;
}QNode,*qQNode; //队列指示
typedef struct {
int length;
qQNode frnt,rear;
}spQueue; void init_Queue(spQueue *Q)
{
(*Q).frnt = NULL;
(*Q).rear = NULL;
(*Q).length = ;
}
bool isEmptyQueue(spQueue Q)
{
if (Q.length == )
{
return true;
}
return false;
}
//进队
void unshiftQueue(spQueue *Q,QueueType elem)
{
//队列空
if (isEmptyQueue(*Q))
{
qQNode n = (qQNode)malloc(sizeof(QNode));
n->data = elem;
n->next = NULL; (*Q).frnt = n;
(*Q).rear = n;
(*Q).length = ;
}
else
{
qQNode n = (qQNode)malloc(sizeof(QNode));
n->data = elem;
n->next = NULL; (*Q).rear->next = n; (*Q).rear = n;
(*Q).length++;
}
} //出队
QueueType shiftQueue(spQueue *Q)
{
if (isEmptyQueue(*Q))
{
printf("Warning:Queue is empty!!!\n");
return NULL;
}
if ((*Q).length == )
{
QueueType sh = (*Q).frnt->data;
(*Q).frnt = NULL;
(*Q).rear = NULL;
(*Q).length = ;
return sh;
}
QueueType sh = (*Q).frnt->data;
(*Q).frnt = (*Q).frnt->next;
(*Q).length--; return sh;
} //打印队列
void prt_que(spQueue que)
{
if (isEmptyQueue(que))
{
return ;
}
qQNode pos = que.frnt;
while(que.rear->next != pos && pos != NULL)
{
printf(" %d ",pos->data);
pos = pos->next;
}
printf("\n");
}
//=============================================================== ///-------
//由节点找节点的序号
IdxType strFindIdx(char ch)
{
int i=;
VertexType *p = g_init_vexs;
while(p != NULL)
{
if(*p == ch)
{
return i;
}
p++;
i++;
}
return i;
} //由序号找节点
VertexType idxFindStr(IdxType i)
{
return g_init_vexs[i];
} void prt_strings(char *p)
{
char *pos = p;
while (NULL != *pos)
{
printf("%c",*pos);
pos++;
}
printf("\n");
} void prt_strArrays(char *p[],int num)
{
char **pos = p;
int i=;
while( *pos != NULL && i < num)
{
prt_strings(*pos);
pos++;
i++;
}
} //自己规定:顶点只能是大写。
bool isVexter(char p)
{
if (p>='A' && p<='Z')
{
return true;
}
return false;
} bool isNumeric(char p)
{
if (p >= '' && p <= '')
{
return true;
}
return false;
} void init_GrapAdjList(GraphAdjList *g,char **str,char **wstr)
{
char **pos = str; int cnt=;
int vcnt = ;
char **wpos = wstr;//weight value //入度清零
int i;
for (i=;i<MAXVEX;i++)
{
(*g).adjList[i].numIn = ;
} while (*pos != NULL) //g_input的每行的首指针
{
int i=;
while(**pos != NULL) //g_input的每行字母
{
if(isVexter(**pos)) //判断是否为顶点(我规定‘A’-‘Z’之间为顶点标志)
{
if (i == ) //建立顶点的节点
{
(*g).adjList[cnt].idx = strFindIdx(**pos);
(*g).adjList[cnt].fitstedge = NULL; i=;
}
else if(i == ) //建立第一个边的节点
{
eNode* n = (eNode*)malloc(sizeof(eNode));
n->idx = strFindIdx(**pos);
n->next = NULL; //weight
while (!isNumeric(**wpos))
{
(*wpos)++;
}
n->weigh = **wpos-'';
(*wpos)++; (*g).adjList[cnt].fitstedge = n;
i=; //添加入度
int iidx = strFindIdx(**pos);
(*g).adjList[iidx].numIn++;
}
else //边节点连接到前一个边节点上
{
eNode* n = (eNode*)malloc(sizeof(eNode));
n->idx = strFindIdx(**pos);
n->next = NULL; //weight
while (!isNumeric(**wpos))
{
(*wpos)++;
}
n->weigh = **wpos-'';
(*wpos)++; //first splist
eNode *r = (*g).adjList[cnt].fitstedge;
while (r->next != NULL)
{
r = r->next;
}
r->next = n; //添加入度
int iidx = strFindIdx(**pos);
(*g).adjList[iidx].numIn++;
}
}
(*pos)++;
} wpos++;
cnt++;
pos++; }
(*g).numVextexs = cnt;
} int TopplogicalSort(GraphAdjList *g)
{
int count=;
eNode *e=NULL; StackType *stack=NULL;
StackType top=;
stack = (StackType *)malloc((*g).numVextexs*sizeof(StackType)); int i; //初始化拓扑序列栈
g_topOfStk = ;
//开辟拓扑序列栈对应的最早开始时间数组
g_etv = (int *)malloc((*g).numVextexs*sizeof(int));
//初始化数组
for (i=;i<(*g).numVextexs;i++)
{
g_etv[i]=;
}
//开辟拓扑序列的顶点数组栈
g_StkAfterTop = (int *)malloc(sizeof(int)*(*g).numVextexs); for (i=;i<(*g).numVextexs;i++)
{
if (!(*g).adjList[i].numIn)
{
stack[++top] = i;
// printf("init no In is %c\n",g_init_vexs[i]);
}
} while(top)
{
int geter = stack[top];
top--; //把拓扑序列保存到拓扑序列栈,为后面做准备
g_StkAfterTop[g_topOfStk++] = geter; printf("%c -> ",g_init_vexs[(*g).adjList[geter].idx]);
count++; //获取当前点出度的点,对出度的点的入度减一(当前点要出图)。
//获取当前顶点的出度点表
e = (*g).adjList[geter].fitstedge;
while(e)
{
int eIdx = e->idx;
//选取的出度点的入度减一
int crntIN = --(*g).adjList[eIdx].numIn;
if (crntIN == )
{
//如果为0,则说明该顶点没有入度了,是下一轮的输出点。
stack[++top] = eIdx;
// printf("running the vex is %c\n",g_init_vexs[e->idx]);
} //求出关键路径
if ((g_etv[geter] + e->weigh) > g_etv[eIdx])
{
g_etv[eIdx] = g_etv[geter] + e->weigh;
} e = e->next;
}
}
if (count < (*g).numVextexs)//如果图本身就是一个大环,或者图中含有环,这样有环的顶点不会进栈而被打印出来。
{
return false;
}
else
{
printf("finish\n");
return true;
} }
void CriticalPath(GraphAdjList g)
{
int i;
int geter;
eNode *e = NULL;
g_topOfStk--;
//1.初始化最迟开始时间数组(汇点的最早开始时间(初值))
g_ltv = (int *)malloc(sizeof(int)*g.numVextexs);
for (i=;i<g.numVextexs;i++)
{
g_ltv[i] = g_etv[g.numVextexs-];
} //2.求每个点的最迟开始时间,从汇点到源点推。
while (g_topOfStk)
{
//获取当前出栈(反序)的序号
geter = g_StkAfterTop[g_topOfStk--];
//对每个出度点
if (g.adjList[geter].fitstedge != NULL)
{
e = g.adjList[geter].fitstedge;
while(e != NULL)
{
int eIdx = e->idx;
if (g_ltv[eIdx] - e->weigh < g_ltv[geter])
{
g_ltv[geter] = g_ltv[eIdx] - e->weigh;
}
e = e->next;
}
}
} int ete,lte;//活动最早开始和最迟开始时间 printf("start:->");
//3.求关键活动,即ltv和etv相等的
for (i=;i<g.numVextexs;i++)
{
if (g.adjList[i].fitstedge)
{
e = g.adjList[i].fitstedge;
while(e)
{
int eIdx = e->idx;
//活动(i->eIdx)最早开始时间:事件(顶点) i最早开始时间
ete = g_etv[i];
//活动(i->eIdx)最迟开始时间:事件(顶点) eIdx 最迟开始时间 减去 活动持续时间
lte = g_ltv[eIdx] - e->weigh;
if (ete == lte)
{
printf("(%c - %c)->",g_init_vexs[i],g_init_vexs[eIdx]);
}
e= e->next;
}
}
}
printf(" end\n");
} int _tmain(int argc, _TCHAR* argv[])
{
GraphAdjList grp;
printf("print Matix: of Vextexs:\n");
prt_strArrays(g_input,);
printf("print Matix: of Weigh:\n");
prt_strArrays(g_input_weigh,); init_GrapAdjList(&grp,g_input,g_input_weigh);
printf("Top sort:\n");
if (!TopplogicalSort(&grp))
{
printf("grp wrong!\n");
} CriticalPath(grp); getchar();
return ;
}

测试结果:

算法学习记录-图——应用之关键路径(Critical Path)的更多相关文章

  1. 算法学习记录-图——最短路径之Dijkstra算法

    在网图中,最短路径的概论: 两顶点之间经过的边上权值之和最少的路径,并且我们称路径上的第一个顶点是源点,最后一个顶点是终点. 维基百科上面的解释: 这个算法是通过为每个顶点 v 保留目前为止所找到的从 ...

  2. 算法学习记录-图——最小生成树之Kruskal算法

    之前的Prim算法是基于顶点查找的算法,而Kruskal则是从边入手. 通俗的讲:就是希望通过 边的权值大小 来寻找最小生成树.(所有的边称为边集合,最小生成树形成的过程中的顶点集合称为W) 选取边集 ...

  3. 算法学习记录-图(DFS BFS)

    图: 目录: 1.概念 2.邻接矩阵(结构,深度/广度优先遍历) 3.邻接表(结构,深度/广度优先遍历) 图的基本概念: 数据元素:顶点 1.有穷非空(必须有顶点) 2.顶点之间为边(可空) 无向图: ...

  4. 算法学习记录-图——应用之拓扑排序(Topological Sort)

    这一篇写有向无环图及其它的应用: 清楚概念: 有向无环图(DAG):一个无环的有向图.通俗的讲就是从一个点沿着有向边出发,无论怎么遍历都不会回到出发点上. 有向无环图是描述一项工程或者系统的进行过程的 ...

  5. 算法学习记录-图——最小路径之Floyd算法

    floyd算法: 解决任意两点间的最短路径的一种算法,可以正确处理有向图或负权的最短路径问题,同时也被用于计算有向图的传递闭包. 设为从到的只以集合中的节点为中间节点的最短路径的长度. 若最短路径经过 ...

  6. 算法学习记录-图——最小生成树之prim算法

    一个连通图的生成树是一个极小的连通子图,它包含图中全部的顶点(n个顶点),但只有n-1条边. 最小生成树:构造连通网的最小代价(最小权值)生成树. prim算法在严蔚敏树上有解释,但是都是数学语言,很 ...

  7. c/c++求解图的关键路径 critical path

    c/c++求解图的关键路径 critical path 上图表示一个工程,工程以V1为起始子工程,V9为终止子工程. 由图可以看出,要开工V5工程,必须在完成工程V2和V3后才可以. 完成V2需要a1 ...

  8. 算法学习导图+经典排序算法PHP实现

    周末抽时间整理下算法,完整导图可点击下面链接获取. 点我看完整算法导图 八种排序算法的php实现 代码如下 拷贝后可直接运行 先上个运行后的图 代码:(有的自己些的 有的根据网友整理) <?ph ...

  9. Manacher回文串算法学习记录

    FROM:  http://hi.baidu.com/chenwenwen0210/item/482c84396476f0e02f8ec230 #include<stdio.h> #inc ...

随机推荐

  1. DevExpress控件扩展之表达式编辑器

    业务需求: 业务工作中经常需要对表格中的数据进行处理,包括过滤.复合计算等.过滤需要有过滤条件,复合计算需要计算公式.这两种场景都需要一个表达式编辑器.GridControl自带过滤条件的表达式编辑器 ...

  2. [bootstrap]模态框总结

    <!--data-backdrop禁止点击空白处关闭模态框,也可以js设置,其他参数可参考官网模态框文档--> <div class="modal fade" i ...

  3. IDEA导入Web项目

    最近尝试着从eclipse.myeclipse转到idea上面来开发. *注:以下仅适用于普通web项目.*  一.导入已有项目 File>Open...>选取自己的项目位置 二.添加ja ...

  4. StringBuffer和StringBuilder区别?

    1. String是不可变类,改变String变量中的值,相当于开辟了新的空间存放新的string变量 2. StringBuffer 可变的类,可以通过append方法改变变量的值,且StringB ...

  5. python IDE-pycharm在virtualenv里安装软件

    1  windows命令行,进入venv下的scripts目录,执行activate.bat进入虚拟环境 2  以selenium安装为例,输入pip install selenium回车开始安装 3 ...

  6. VUE在页面没加载完的时候会显示原代码的处理方法

    CSS: [v-cloak] { display: none; } HTML : <div v-cloak> {{ message }} </div> 其中 v-cloak官方 ...

  7. POJ-2718 Smallest Difference---DFS

    题目链接: https://vjudge.net/problem/POJ-2718 题目大意: 有一列数,对其任意分成两组,每组按一定顺序可以组成一个数.问得到的两个数的差最小是多少. 思路: 直接d ...

  8. Uva 11997 多路归并

    题目链接:https://uva.onlinejudge.org/external/119/11997.pdf 题意: k*k的矩阵,从每一行中选一个元素加起来,可以得到 kk个和,求前 k 个最小值 ...

  9. 课程设计__继承与派生,重载<<

    ///继承与派生 #include <iostream> using namespace std; class Point { public: Point (,):x(a),y(b) {} ...

  10. 20145238-荆玉茗 《Java程序设计》第四次实验报告

    20145238<Java程序设计>第四次实验报告 实验四 Android环境搭建 实验内容 1.搭建Android环境 2.运行Android 3.修改代码,能输出学号 实验步骤 搭建A ...