• UVA-116


    题意:

    给一个mn(m<=10n<=100)的整数矩阵,从第一列任何一个位置出发每次向右,右上或者右下走一格,要求经过的整数之和最小。整个矩阵是环形的,即第一行的上一行是最后一行,最后一行的下一行是第一行。输出路径上每一行的行号,要求字典序最小。

    思路:

    定义状态dp[i][j]为从第一列出发到第j列第i行的最小值是多少,转移方程上面已经给出,照着转移就行,难点在于字典序最小,因为我们定义的的dp方程是正向递推的,所以对于判断字典序最小有点麻烦,对于两个相等的结果,需要逆向找出他们的起点来判断字典序谁最小,在代码简洁程度上远不如lrj,但不失为一种思路。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    int mp[100][200],pre[100][200];
    int ans[200];int n,m;
    void Debug()
    {
        printf("***********************************
    ");
        for(int i = 1;i<=n;++i)
        {
            for(int j = 1;j<=m;++j)
                printf("%2d ",mp[i][j]);
            printf("
    ");
        }
    }
    void check(int &a,int b,int &c,int j)
    {
        if(mp[b][j-1]<mp[a][j-1])
        {
            a = b;
            c = mp[b][j-1];
        }
        else if(mp[b][j-1]==mp[a][j-1])
        {
            vector<int>t1(m+1),t2(m+1);
            int k = a;
            int i =j-1;
            while(i>=1)
            {
                t1[i] = k;
                k = pre[k][i];
                --i;
            }
            k = b;
            i = j-1;
            while(i>=1)
            {
                t2[i] = k;
                k = pre[k][i];
                --i;
            }
            for(int  i = 1;i<j;++i)
            {
                if(t2[i]!=t1[i])
                {
                    if(t2[i]<t1[i])
                    {
                         a = b;
                    c = mp[b][j-1];
                    }
    
                    return ;
                }
            }
        }
        return ;
    }
    int main()
    {
       //freopen("in.txt","r",stdin);
        //freopen("out.txt","w",stdout);
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            for(int i = 1;i<=n;++i)
            {
                for(int j = 1;j<=m;++j)
                {
                    scanf("%d",&mp[i][j]);
                    pre[i][j] = -1;
                }
            }
            if(m==1)
            {
                int mi = mp[1][1],id = 1;
                for(int i = 1;i<=n;++i)
                {
                    if(mp[i][1]<mi)
                    {
                        mi = mp[i][1];
                        id = i;
                    }
                }
                printf("%d
    %d
    ",id,mi);
                continue;
            }
            for(int i = 2;i<=m;++i)
            {
                for(int j = 1;j<=n;++j)
                {
                    int tmp = j;
                    --tmp;
                    if(tmp==0)
                        tmp = n;
                    int id = tmp,mi = mp[tmp][i-1];
                  //  cout << "i = " << i << " " << " j = " << j << endl;
                    //cout << id << " " << mi << endl;
                    tmp = j,
                    check(id,tmp,mi,i);
                    tmp = j+1;
                    if(tmp>n)
                        tmp = 1;
                    check(id,tmp,mi,i);
                    mp[j][i]+=mi;
                    pre[j][i] = id;
                }
            }
            //Debug();
            for(int i =1;i<=m;++i)
                ans[i] = n;
            int mi = mp[1][m];
            for(int i =2;i<=n;++i)
                mi = min(mi,mp[i][m]);
            for(int i =1;i<=n;++i)
            {
                if(mp[i][m]==mi)
                {
                    vector<int> t(m+1);
                    int k = i,j= m;
                    while(j>=1)
                    {
                        t[j] =k;
                        //--j;
                        k = pre[k][j];
                        --j;
                    }
                    bool flag = false;
                    for(int i = 1;i<=m;++i)
                    {
                        if(t[i]!=ans[i])
                        {
                            if(t[i]<ans[i])
                            flag = true;
                            break;
                        }
                    }
                    if(flag)
                    {
                        for(int i =1;i<=m;++i)
                            ans[i] = t[i];
                    }
                }
            }
            printf("%d",ans[1]);
            for(int i  =2;i<=m;++i)
                printf(" %d",ans[i]);
            printf("
    ");
            printf("%d
    ",mi);
        }
        return 0;
    }
  • 相关阅读:
    c++对象的生命周期
    VS2010在工具栏上创建查找组合框,即:CMFCToolBar中加入CMFCToolBarComboBoxButton
    VS2010 MFC多文档中的工具栏CMFCToolBar停靠的问题
    Nginx使用部署方案
    [软件测试] 软件测试基础问答
    OAI 安装好之后网络配置。
    Ubuntu 18.04 安装OAI (EPC+eNB+UE)
    build.sh安装依赖包
    [Linux简单操作] 查询设备相关信息
    [计算机基础] 基础问答
  • 原文地址:https://www.cnblogs.com/baihualiaoluan/p/12349901.html
Copyright © 2020-2023  润新知