zoukankan      html  css  js  c++  java
  • UVA 10564


    本文出自   http://blog.csdn.net/shuangde800





    题意:



    给一个相上面的图。要求从第一层走到最下面一层,只能往左下或右下走,经过的数字之和为sum。
    问有多少条路径之和刚好等于S? 如果有的话,输出字典序最小的路径。



    思路:

    f[i][j][k] 代表从(i,j)点往下走到最后一层和为k的方案数
    那么,显然可以得到状态转移:
    f[i][j][k] = f[i+1][left][k-val] + f[i+1][right][k-val],  val=(i,j)格上的数字,left是往坐下走的坐标,right往右下走的坐标




    代码:
    /**==========================================
     *   This is a solution for ACM/ICPC problem
     *
     *   @author: shuangde
     *   @blog: blog.csdn.net/shuangde800
     *   @email: zengshuangde@gmail.com
     *===========================================*/
    
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<cmath>
    #include<cstring>
    using namespace std;
    
    typedef long long int64;
    const int INF = 0x3f3f3f3f;
    const double PI  = acos(-1.0);
    
    int n, s;
    int hourGlass[50][22];
    int64 f[50][22][510];
    
    
    void input(){
        for(int i=1; i<=n; ++i)
            for(int j=1; j<=n-i+1; ++j) 
                scanf("%d", &hourGlass[i][j]);
    
        for(int i=n+1; i<=2*n-1; ++i)
            for(int j=1; j<=i+1-n; ++j)
                scanf("%d", &hourGlass[i][j]); 
    
    }
    
    void print_path(int i, int j, int sum){
        if(i >= 2*n-1) return;
        int val = hourGlass[i][j];
        if(i<n){ 
            if(j>1 && f[i+1][j-1][sum-val]){
                printf("L");
                print_path(i+1, j-1, sum-val);
                return ;
            } 
            printf("R");
            print_path(i+1, j, sum-val);
    
        }else{
            if(f[i+1][j][sum-val]){
                printf("L"); 
                print_path(i+1, j, sum-val);
                return;
            } 
            printf("R"); 
            print_path(i+1, j+1, sum-val);
        }
    }
    
    int main(){
    
        while(~scanf("%d%d", &n, &s) && n+s){
    
            input();
            memset(f, 0, sizeof(f));
    
            // 初始化最下面一行
            for(int i=1; i<=n; ++i)
                f[2*n-1][i][hourGlass[2*n-1][i]] = 1;
    
            // 下半部分dp
            for(int i=2*n-2; i>=n; --i){
                for(int j=1; j<=i+1-n; ++j){
                    for(int v=hourGlass[i][j]; v<=s; ++v){
                        int w = hourGlass[i][j];
                        f[i][j][v] = f[i+1][j][v-w] + f[i+1][j+1][v-w]; 
                    }
                } 
            }
    
            // 上半部分dp
            int64 ans = 0;
            for(int i=n-1; i>=1; --i){
                for(int j=1; j<=n-i+1; ++j){
                    for(int v=hourGlass[i][j]; v<=s; ++v){
                        int w = hourGlass[i][j];
                        if(j>1) f[i][j][v] += f[i+1][j-1][v-w];
                        if(j<n-i+1) f[i][j][v] += f[i+1][j][v-w];
                    }
                    if(i==1) ans += f[1][j][s];
                } 
            }
    
            cout << ans << endl;
            for(int i=1; i<=n; ++i){
                if(f[1][i][s]){
                    printf("%d ", i-1); 
                    print_path(1, i, s);
                    break;
                }
            }
            puts("");
    
        }
        return 0;
    }
    
















     


  • 相关阅读:
    关于数据库字符集编码及通用软件产品的设计表结构的注意事项
    记一次调用第三方接口,对方获取到参数乱码问题
    Java获取固定格式日期&计算日期相差时长
    Redis之雪崩、穿透、击穿
    [LeetCode] 两数相加 (JavaScript 解法)
    React hooks 获取 dom 引用
    PHP + Redis 实现定任务触发
    测试PHP几种方法写入文件的效率与安全性
    如何调整firefox鼠标滚轮速度
    美美Apple ID 注册教程
  • 原文地址:https://www.cnblogs.com/aukle/p/3235613.html
Copyright © 2011-2022 走看看