• 多阶段决策问题(UVa 116)


    在回溯法中,每个决策对应于给一个节点产生新的子树,而解的生成过程对应一颗解答树,节点的层数就是下一个待填充位置$cur$。

    在多阶段决策的最优化问题,大多可以用dp解决,状态转移则类似于回溯法中的解答树。

    UVa 116

    $d(i,j)$表示从第此处出发到达最后一列的最小和,要求字典序最小,就同时要记录行号的最小值。

    代码:

     1 //
     2 //  main.cpp
     3 //  UVa 116
     4 //
     5 //  Created by Yanbin GONG on 12/3/2018.
     6 //  Copyright © 2018 Yanbin GONG. All rights reserved.
     7 //
     8 
     9 #include <iostream>
    10 #include <stdio.h>
    11 #include <string>
    12 #include <string.h>
    13 #include <algorithm>
    14 #include <cmath>
    15 
    16 using namespace std;
    17 
    18 int m,n;
    19 int cell[15][105];
    20 int d[15][105];
    21 int path[15][105]; //记录从该处应该走到的下一个点
    22 int tmp;
    23 int ans;
    24 int startNode;
    25 //int updown[3] = {-1,0,1}; 写在dp中,方便改变状态,满足在上下边时候的移动
    26 
    27 
    28 int main(){
    29     while(cin>>n>>m){
    30         memset(d,0x3f,sizeof(d));
    31         ans = 0x3f3f3f3f;
    32         for(int i=1;i<=n;i++){
    33             for(int j=1;j<=m;j++){
    34                 cin>>cell[i][j];
    35             }
    36             d[i][m] = cell[i][m];//初始化边界
    37         }
    38         //dp
    39         for(int j=m;j>1;j--){
    40             
    41             for(int i=1;i<=n;i++){
    42                 int updown[3] = {i-1,i,i+1}; //表示接下来处在的行
    43                 if(i==1) updown[0] = n;
    44                 if(i==n) updown[2] = 1;
    45                 //排序找到最小字典序的核心代码!因为这个WA了
    46                 sort(updown,updown+3); //排序找到最小字典序的核心代码!因为这个WA了
    47                 //排序找到最小字典序的核心代码!因为这个WA了
    48                 for(int k=0;k<3;k++){
    49                     tmp = d[i][j] + cell[updown[k]][j-1]; //到[][j-1]的总成本
    50                     if(tmp<d[updown[k]][j-1]){
    51                         d[updown[k]][j-1] = tmp;
    52                         path[updown[k]][j-1] = i;//反向记录从[][j-1]走到[i][j]
    53                     }
    54                 }
    55             }
    56         }
    57         //找到最优解的开始
    58         for(int i=1;i<=n;i++){
    59             if(ans>d[i][1]){
    60                 ans = d[i][1];
    61                 startNode = i;
    62             }
    63         }
    64         //print
    65         printf("%d",startNode);
    66         int nextNode = path[startNode][1];
    67         for(int j=1;j<=m;j++){
    68             printf(" %d",nextNode);
    69             nextNode = path[nextNode][j];
    70         }
    71         printf("
    %d
    ",ans);
    72     }
    73     return 0;
    74 }
    View Code

    这题要注意将$updown$更新后重新排序一遍,这样才能确定找到的字典序是最小的

  • 相关阅读:
    Find the capitals
    Area of a Circle
    SequenceSum
    使用Eclipse设定Android开发环境
    hdu 1290 竭诚为杭州电礼物50周年
    oracle connect by 说明
    CSS截取字符串,额外的文本显示以省略号
    动态规划——背包问题
    【MySQL笔记】mysql来源安装/配置步骤和支持中国gbk/gb2312编码配置
    博客搬到了http://xianglong.me
  • 原文地址:https://www.cnblogs.com/cmbyn/p/8552503.html
Copyright © 2020-2023  润新知