1. 程式人生 > >多段圖的最短路徑問題-----動態規劃法

多段圖的最短路徑問題-----動態規劃法

對多段圖,求最短路徑,如圖:

對其使用動態規劃法:

階段:將圖中的頂點劃分5個階段,k

狀態:每個階段有幾種供選擇的點s

決策:當前狀態應在前一個狀態的基礎上獲得。決策需要滿足規劃方程

規劃方程:f(k)表示狀態k到終點狀態的最短距離。

初始條件:f(k)=0;

方程:f(k-1)=min{f(k)+W(k-1,k)}其中W(k-1,k)表示狀態k-1到狀態k的距離

程式碼如下:

#include<limits.h>
#include<iostream>
using namespace std;
void Init_Graph(int N,int k,int** S, int **C)
{
	int X;
	int i,j;
	int temp=N;
	cout<<"輸入邊的長度:輸入1 2 4 表示點1 與 2的邊的長度為 4:首數字為0表示結束輸入"<<endl;
	cin>>i;
	while (i!=0)
	{
		cin>>j;
		cin>>C[i][j];
		cin>>i;
	}
	cout<<"輸入每個階段有哪些點:輸入:X 1 2 3表示該階段有X個點,分別為1,2,3:"<<endl;
	for (i=1;i<=k;i++)
	{
		cout<<"輸入第"<<i<<"階段的狀態的點數:";
		cin>>X;
		cout<<"這些點分別為:";
		for (j=0;j<X;j++)
		{
			cin>>S[i][j];
		}
	}
}
void Plan(int N,int k,int **S,int **F,int** C,int *result)
{
	int i,j,t=N;
	int m;
	int point;
	//cout<<S[k][0]<<" ";
	point=S[k][0];
	for (i=k-1;i>=1;i--)//階段
	{
		j=0;//i階段的狀態
		while (S[i][j]!=0)//狀態
		{
			m=0;//i+1階段的狀態
			F[i][j]=INT_MAX;
			if (C[S[i][j]][point]==INT_MAX)
			{
				while (S[i+1][m]!=0)
				{
					if (C[S[i][j]][S[i+1][m]]!=INT_MAX)
					{
						if (F[i][j]>(F[i+1][m]+C[S[i][j]][S[i+1][m]]))
						{
							F[i][j] = F[i+1][m] + C[S[i][j]][S[i+1][m]];
							result[S[i][j]]=S[i+1][m];
							t--;
						}
					}
					m++;
				}
			}
			else
			{
				while (S[i+1][m]!=0)
				{
					if (F[i][j]>(F[i+1][m]+C[S[i][j]][S[i+1][m]]))
					{
						F[i][j] = F[i+1][m] + C[S[i][j]][S[i+1][m]];
						result[S[i][j]]=S[i+1][m];
						t--;
					}
					m++;
				}
			}
			j++;
		}
	}
	cout<<"符合條件的點為:"<<endl;
	t=0;
	result[t]=1;
	cout<<result[t]<<" ";
	t=result[t];
	while (t<N)
	{
		cout<<result[t]<<" ";
		t=result[t];
	}
	cout<<endl<<"最短距離為:";
	cout<<F[i+1][0]<<endl;
}
int main(int argc,char *argv[])
{
	int N,k;
	int i,j;
	int **C,**S,**F;//C:邊的長度,S;每個階段的狀態;F:記錄每個階段的狀態中的點到終點的距離
	int *result;//輸出點
	cout<<"輸入點的個數:";
	cin>>N;
	cout<<"輸入階段數:";
	cin>>k;
	C=new int*[N+1];
	//C=(int **)malloc(sizeof(int*)*(N+1));
	for (i=0;i<N+1;i++)
	{
		//C[i]=(int *)malloc(sizeof(int)*(N+1));
		C[i]=new int[N+1];
		for (j=0;j<N+1;j++)
		{
			C[i][j]=INT_MAX;
		}
	}
	S= new int*[N+1];
	for (i=0;i<N+1;i++)
	{
		S[i]=new int[N+1];
		memset(S[i],0,sizeof(int)*(N+1));
	}
	F=new int *[N+1];
	for (i=0;i<N+1;i++)
	{
		F[i]=new int [N+1];
		for (j=0;j<N+1;j++)
		{
			F[i][j]=0;
		}
	}
	result=new int[N+1];
	memset(result,0,sizeof(int)*(k+1));
	Init_Graph(N,k,S,C);
	/*
	多段圖的動態規劃方法
	階段:k
	狀態:Sk:即每個階段可供選擇的點的位置
	決策:u
	規劃方程:f(k)=min(f(k+1)+邊u的長度。
	f(k)表示:k點到終點的最短路徑長度
	初始值:F(k)=0;
    */
	Plan(N,k,S,F,C,result);
	delete []result;
	for (i=0;i<N+1;i++)
	{
		delete []C[i];
	}
	delete []C;
	for (i=0;i<N+1;i++)
	{
		delete []S[i];
	}
	delete []S;
	for (i=0;i<N+1;i++)
	{
		delete []F[i];
	}
	delete []F;
	return 0;
}



執行結果如下: