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

(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. 初学:react-native 轮播图

    参考资料:http://reactscript.com/react-native-card-carousel-component/ import React, {Component} from 're ...

  2. matlab练习程序(粒子群优化PSO)

    算法没有和图像处理直接相关,不过对于图像分类中的模式识别相关算法,也许会用到这个优化算法. 算法步骤: 1.首先确定粒子个数与迭代次数. 2.对每个粒子随机初始化位置与速度. 3.采用如下公式更新每个 ...

  3. 第五章 存储过程&触发器

    1.前言 2.存储过程和触发器->存储过程 ·理解:是一组SQL命令集合,经过预编译存放在系统中:就像java程序里的方法,可以重复的被调用: 在日常的数据库操作中,会有大量的T-SQL批处理. ...

  4. Description Resource Path Location Type Java compiler level does not match the version of the installed Java project facet Unknown Faceted Project Problem (Java Version Mismatch)

    project 编译问题,需要三处的jdk版本要保持一致,才能编译通过. 1.在项目上右键properties->project Facets->修改右侧的version  保持一致 2. ...

  5. Laravel 5.5 官方推荐 Nginx 配置学习

    Laravel 5.5 版本官方放出了 Nginx 服务器的配置,中文文档:服务器配置 Nginx server { listen 80; server_name example.com; root ...

  6. 通过CSS3实现:鼠标悬停图片360度旋转效果

    效果很好玩,代码很简单: 效果: 鼠标放置在图片上:360度顺时针旋转 鼠标离开图片:图片260度逆时针旋转 只要将下面代码拷贝过去,并将图片改成你想要的就可以看到效果 <!doctype ht ...

  7. "提取位于北坡的各类用地面积信息"的程序设计与实现

    "提取位于北坡的各类用地面积信息"的程序设计与实现  程序员:左正康         发表时间:2013/12/20 14:24       代号:黑眼圈的日子 第一步:导入dem ...

  8. (转载)arcgis for js - 解决加载天地图和WMTS服务,WMTS服务不显示的问题,以及wmts服务密钥。

    1 arcgis加载天地图和wmts服务 arcgis for js加载天地图的例子网上有很多,这里先不写了,后期有空再贴代码,这里主要分析下WMTS服务为什么不显示,怎么解决. 条件:这里的WMTS ...

  9. hdu-2838 Cow Sorting---逆序对的花费

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2838 题目大意: 就是求将之前的排列变成一个递增的排列,每交换两个数的代价为两个数的和,求变成递增的 ...

  10. POJ-1422 Air Raid---二分图匹配&最小路径覆盖

    题目链接: https://vjudge.net/problem/POJ-1422 题目大意: 有n个点和m条有向边,现在要在点上放一些伞兵,然后伞兵沿着图走,直到不能走为止 每条边只能是一个伞兵走过 ...