动态规划——多段图优化求解

#include<stdio.h>

int V[50][50];
int a[50],b[20];
int static k,n,m;

void createGraph()
{
    int i,j,t,s;
    printf("请输入结点数:");
    scanf("%d",&n);
    for(i=0; i<=n; i++)
        for(j=0; j<=n; j++)
            V[i][j]=0;//初始化V[i][j]=0,表示两结点没有边相连
    printf("输入图的层数:");
    scanf("%d",&k);
    printf("请输入每层的结点数的最大编号:");
    a[0]=0;
    for(i=1; i<=k; i++)
        scanf("%d",&a[i]);
    printf("请输入边数:");
    scanf("%d",&m);
    printf("请输入结点之间的关系(如:结点i和结点j的距离为s,则输入i,j,s)\n");
    for(t=1; t<=m; t++)
    {
        scanf("%d%d%d",&i,&j,&s);
        V[i][j]=s;
    }
}
int Backward()//向后求解法
{
    int i,j,t,r;
    for(i=a[1]+1; i<=a[2]; i++) //把第二层每个结点i与第一层结点s的边距赋值给V[i][i]
        V[i][i]=V[1][i];
    for(r=2; r<k; r++) //向后逐层求解
        for(i=a[r-1]+1; i<=a[r]; i++) //遍历第r层的每个结点i与第(r+1)层结点j之间的边距,选择此刻最优解
            for(j=a[r]+1; j<=a[r+1]; j++)
            {
                if(V[i][j]!=0&&V[j][j]==0)//第一次把此刻路径长度赋给V[j][j]
                    V[j][j]=V[i][i]+V[i][j];
                else if(V[i][j]!=0&&V[j][j]!=0)
                {
                    if((V[i][i]+V[i][j])<V[j][j])
                        V[j][j]=V[i][i]+V[i][j];
                }
            }

    j=-1;
    b[4]=0;
    for(r=k-1; r>=2; r--)
        for(i=a[r]+1; i<=a[r+1]; i++)
        {
            if(b[r]==j)
                break;
            for(j=a[r-1]+1; j<=a[r]; j++)
                if((V[i][i]-V[j][i])==V[j][j])
                {
                    b[r]=j;
                    break;
                }

        }

    return V[n][n];
}
int Forward()//向前求解法
{
    int i,j,t,r;
    for(i=a[k-2]+1; i<=a[k-1]; i++) //把第二层每个结点i与第一层结点s的边距赋值给V[i][i]
        V[i][i]=V[i][a[k]];
    for(r=k-1; r>1; r--) //向前逐层求解
        for(j=a[r-1]+1; j<=a[r]; j++)//遍历第r层的每个结点i与第(r-1)层结点j之间的边距,选择此刻最优解
            for(i=a[r-2]+1; i<=a[r-1]; i++)
            {
                if(V[i][j]!=0&&V[i][i]==0)//第一次把此刻路径长度赋给V[j][j]
                    V[i][i]=V[j][j]+V[i][j];
                else if(V[i][j]!=0&&V[i][i]!=0)
                {
                    if((V[j][j]+V[i][j])<V[i][i])
                        V[i][i]=V[j][j]+V[i][j];
                }
            }

    for(r=2; r<=k-1; r++)
        for(i=a[r-2]+1; i<=a[r-1]; i++)
        {
            for(j=a[r-1]+1; j<=a[r]; j++)
                if((V[i][i]-V[i][j])==V[j][j])
                {
                    b[r]=j;
                    break;
                }
            i=j;
            r++;


        }

    return V[1][1];
}
int main()
{
    int i,j,r,sp;
    createGraph();
    b[1]=1;
    b[k]=n;
    //sp=Forward();
    sp=Backward();
    printf("最短路径长度为:%d\n",sp);
    printf("最短路径为:");
    printf("%d",b[1]);
    for(i=2; i<=k; i++)
    printf("->%d",b[i]);
    return 0;
}

 

运行结果

向后求解法:

向后求解法:

多段图:

相关数据:

1 2 9
1 3 7
1 4 3
1 5 2
2 6 4
2 7 2
2 8 1
3 6 2
3 7 7
4 8 11
5 7 11
5 8 8
6 9 6
6 10 5
7 9 4
7 10 3
8 10 5
8 11 6
9 12 4
10 12 2
11 12 5

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值