Codeforces2B--动态规划(路径DP)

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <string.h>
#include <algorithm>

typedef short int int16;///32767
typedef int int32;///2147483647
typedef long long int64;///9223372036854775807
const double PI=acos(-1.0);///3.141593
const long long MOD=(long long)1E9+7LL;///1000000007
template <class T> T Susake_pow(T a,T b)///pow
{T res;if(b==0) return 1;else while((b&1)==0){b>>=1;a*=a;}res=a;b>>=1;while(b!=0){a*=a;if((b&1)!=0)res*=a;b>>=1;}return res;}
template<class T> inline T gcd(T a,T b)///gcd
{if(a<0)return gcd(-a,b);if(b<0)return gcd(a,-b);return (b==0)?a:gcd(b,a%b);}
template<class T> inline T lcm(T a,T b)///lcm
{if(a<0)return lcm(-a,b);if(b<0)return lcm(a,-b);return a*(b/gcd(a,b));}
template<class T> inline char *Susake_nsystem(T n)///itoa(26)
{T t=0,i;char *s,*p;s=(char *)malloc(sizeof(char)*1000);p=(char *)malloc(sizeof(char)*1000);
while(n){s[t]=n%26+64;if(s[t]==64){s[t]+=26;n-=26;}t++;n/=26;}s[t]=‘\0‘;for(i = 0; i < t; i++)p[i]=s[t-1-i];p[i]=‘\0‘;free(s);return p;}
int Susake_msystem(char *s)///atoi(26)
{int len=strlen(s),i,sum=0;char p[1000];for(i=0;i<len;i++)p[i]=s[len-1-i]-64;for(i=0;i<len;i++)sum+=p[i]*Susake_pow(26,i);return sum;}

int a[1003][1003];
char path[2003];

void judge(int &x2, int &x5, int n)
{
    x2 = x5 = 0;
    while(n % 5 == 0 && n)
    {
        n /= 5;
        x5++;
    }
    while(n % 2 == 0 && n)
    {
        n /= 2;
        x2++;
    }
}

struct Node
{
    int Susake2;
    int Susake5;
    int px, py;
};

Node Susake[1003][1003], dp1[1003][1003], dp2[1003][1003];

int main(int argc, char *argv[])
{
    int n, x2, x5, Min1, Min2, k1, k2, flag, ex, ey, tx, ty, si, sj, God;
    memset(a, 0, sizeof(a));
    memset(Susake, 0, sizeof(Susake));
    memset(path, 0, sizeof(path));
    scanf("%d", &n);
    flag = 0;
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++)
        {
            scanf("%d", &a[i][j]);
            if(a[i][j] == 0 && flag == 0)
            {
                flag = 1;
                si = i;
                sj = j;
            }
            judge(x2, x5, a[i][j]);
            Susake[i][j].Susake2 = x2;
            Susake[i][j].Susake5 = x5;
        }
    //bround
    dp1[0][0].Susake2 = 0;
    dp1[1][0].Susake2 = 0;
    dp1[0][1].Susake2 = 0;
    dp2[0][0].Susake5 = 0;
    dp2[1][0].Susake5 = 0;
    dp2[0][1].Susake5 = 0;
    for(int i = 2; i <= n; i++)
    {
        dp1[i][0].Susake2 = 1000000009;
        dp1[0][i].Susake2 = 1000000009;
        dp2[i][0].Susake5 = 1000000009;
        dp2[0][i].Susake5 = 1000000009;
    }
    //according to 2 dp
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++)
        {
            dp1[i][j].Susake2 = std::min(dp1[i - 1][j].Susake2, dp1[i][j - 1].Susake2) + Susake[i][j].Susake2;
            //Save path
            if(dp1[i - 1][j].Susake2 < dp1[i][j - 1].Susake2)
            {
                dp1[i][j].px = i - 1;
                dp1[i][j].py = j;
            }
            if(dp1[i - 1][j].Susake2 >= dp1[i][j - 1].Susake2)
            {
                dp1[i][j].px = i;
                dp1[i][j].py = j - 1;
            }
        }
    Min1 = dp1[n][n].Susake2;
    //according to 5 dp
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++)
        {
            dp2[i][j].Susake5 = std::min(dp2[i - 1][j].Susake5, dp2[i][j - 1].Susake5) + Susake[i][j].Susake5;
            //Save path
            if(dp2[i - 1][j].Susake5 < dp2[i][j - 1].Susake5)
            {
                dp2[i][j].px = i - 1;
                dp2[i][j].py = j;
            }
            if(dp2[i - 1][j].Susake5 >= dp2[i][j - 1].Susake5)
            {
                dp2[i][j].px = i;
                dp2[i][j].py = j - 1;
            }
        }
    Min2 = dp2[n][n].Susake5;
    //print the path
    dp1[1][1].px = 1;
    dp1[1][1].py = 1;
    dp2[1][1].px = 1;
    dp2[1][1].py = 1;
    God = 0;
    if(std::min(Min1, Min2) > 1 && flag)
    {
        printf("%d\n", 1);
        for(int i = 2; i <= si; i++)
            printf("D");
        for(int i = 2; i <= sj; i++)
            printf("R");
        for(int i = si + 1; i <= n; i++)
            printf("D");
        for(int i = sj + 1; i <= n; i++)
            printf("R");
        printf("\n");
    }
    else
    {
        if(Min1 <= Min2)
        {
            k1 = 0;
            tx = ty = n;
            ex = tx; ey = ty;
            tx = dp1[tx][ty].px;
            ty = dp1[tx][ty].py;
            if(a[ex][ey] == 0)
                God = 1;
            if(a[tx][ty] == 0)
                God = 1;
            if(tx < ex)
            {
                k1++;
                path[k1] = ‘D‘;
            }
            if(ty < ey)
            {
                k1++;
                path[k1] = ‘R‘;
            }
            ex = tx; ey = ty;
            while(tx != 1 || ty != 1)
            {
                tx = dp1[ex][ey].px;
                ty = dp1[ex][ey].py;
                if(a[tx][ty] == 0)
                God = 1;
                if(tx < ex)
                {
                    k1++;
                    path[k1] = ‘D‘;
                }
                if(ty < ey)
                {
                    k1++;
                    path[k1] = ‘R‘;
                }
                ex = tx; ey = ty;
            }
            if(God == 1)
                printf("1\n");
            else
                printf("%d\n", std::min(Min1, Min2));
            for(int i = k1; i >= 1; i--)
                printf("%c", path[i]);
            printf("\n");
        }
        else
        {
            k2 = 0;
            tx = ty = n;
            ex = tx; ey = ty;
            tx = dp2[tx][ty].px;
            ty = dp2[tx][ty].py;
            if(a[ex][ey] == 0)
                God = 1;
            if(a[tx][ty] == 0)
                God = 1;
            if(tx < ex)
            {
                k2++;
                path[k2] = ‘D‘;
            }
            if(ty < ey)
            {
                k2++;
                path[k2] = ‘R‘;
            }
            ex = tx; ey = ty;
            while(tx != 1 || ty != 1)
            {
                tx = dp2[ex][ey].px;
                ty = dp2[ex][ey].py;
                if(a[tx][ty] == 0)
                God = 1;
                if(tx < ex)
                {
                    k2++;
                    path[k2] = ‘D‘;
                }
                if(ty < ey)
                {
                    k2++;
                    path[k2] = ‘R‘;
                }
                ex = tx; ey = ty;
            }
            if(God == 1)
                printf("1\n");
            else
                printf("%d\n", std::min(Min1, Min2));
            for(int i = k2; i >= 1; i--)
                printf("%c", path[i]);
            printf("\n");
        }
    }
    return 0;
}
时间: 2024-11-07 07:43:56

Codeforces2B--动态规划(路径DP)的相关文章

Leetcode之动态规划(DP)专题-63. 不同路径 II(Unique Paths II)

初级题目:Leetcode之动态规划(DP)专题-62. 不同路径(Unique Paths) 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” ). 机器人每次只能向下或者向右移动一步.机器人试图达到网格的右下角(在下图中标记为“Finish”). 现在考虑网格中有障碍物.那么从左上角到右下角将会有多少条不同的路径? 网格中的障碍物和空位置分别用 1 和 0 来表示. 说明:m 和 n 的值均不超过 100. 示例 1: 输入: [   [0,0,0],  

POJ 3071 Football (动态规划-概率DP)

Football Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2768   Accepted: 1412 Description Consider a single-elimination football tournament involving 2n teams, denoted 1, 2, -, 2n. In each round of the tournament, all teams still in the

UVA 624 CD 记录路径DP

开一个数组p 若dp[i-1][j]<dp[i-1][j-a[i]]+a[i]时就记录下p[j]=a[i];表示此时放进一个轨道 递归输出p #include <stdio.h> #include <string.h> #include <stdlib.h> #include <limits.h> #include <malloc.h> #include <ctype.h> #include <math.h> #in

hdu2196 Computer(树上最长路径 dp)

题目链接:点击打开链接 题意描述:给定一棵树,树上每条边的有一个权值,问从任意一个点出发能走得最长路径是多少? 解题思路:树上最长路径 dp 1.任意找一个点作为根节点,将无根树转化为有根树 2.在dfs过程中更新f[i],g[i],其中f[i]记录以i为节点向下扩展最长路,g[i]为次长路,并用mark标记每个节点最长路的儿子节点 3.在dfs1的过程中更新h[i],h[i]表示以i为节点的向上扩展的最长路 代码: #pragma comment(linker,"/STACK:10240000

POJ 2151 Check the difficulty of problems (动态规划-概率DP)

Check the difficulty of problems Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4522   Accepted: 1993 Description Organizing a programming contest is not an easy job. To avoid making the problems too difficult, the organizer usually exp

HDU 4336 Card Collector(动态规划-概率DP)

Card Collector Problem Description In your childhood, do you crazy for collecting the beautiful cards in the snacks? They said that, for example, if you collect all the 108 people in the famous novel Water Margin, you will win an amazing award. As a

初探动态规划(DP)

学习qzz的命名,来写一篇关于动态规划(dp)的入门博客. 动态规划应该算是一个入门oier的坑,动态规划的抽象即神奇之处,让很多萌新 萌比. 写这篇博客的目标,就是想要用一些容易理解的方式,讲解入门动态规划的真正意义. 奶萌兔的温馨提示:建议先理解dfs哦~(本文以一种较为新奇的方式解释DP) 动态规划 那什么是动态规划? 来问问神奇的奶萌兔吧(强行盗梗)! (奶萌兔来给你讲解啦~虽然还在睡觉=w=) 动态规划(英语:Dynamic programming,简称DP)是一种在数学.管理科学.计

[hdu contest 2019-07-29] Azshara&#39;s deep sea 计算几何 动态规划 区间dp 凸包 graham扫描法

今天hdu的比赛的第一题,凸包+区间dp. 给出n个点m个圆,n<400,m<100,要求找出凸包然后给凸包上的点连线,连线的两个点不能(在凸包上)相邻,连线不能与圆相交或相切,连线不能相交但是可以有公共端点. 首先找出凸包,然后把n*n条边和m个圆算点到直线距离验证一下边是否与圆相交存到e[n][n]里. 然后显然是一个dp,但是我开始看错题目了以为不能有公共端点,能有公共端点的情况考虑一下像一个找三角形的过程,就是区间dp. 区间dp有一点妙的地方是最大区间范围是凸包点数而不用+1,因为连

Leetcode之动态规划(DP)专题-62. 不同路径(Unique Paths)

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” ). 机器人每次只能向下或者向右移动一步.机器人试图达到网格的右下角(在下图中标记为“Finish”). 问总共有多少条不同的路径? 例如,上图是一个7 x 3 的网格.有多少可能的路径? 说明:m 和 n 的值均不超过 100. 示例 1: 输入: m = 3, n = 2 输出: 3 解释: 从左上角开始,总共有 3 条路径可以到达右下角. 1. 向右 -> 向右 -> 向下 2. 向右 -> 向下

动态规划——线性dp

我们在解决一些线性区间上的最优化问题的时候,往往也能够利用到动态规划的思想,这种问题可以叫做线性dp.在这篇文章中,我们将讨论有关线性dp的一些问题. 在有关线性dp问题中,有着几个比较经典而基础的模型,例如最长上升子序列(LIS).最长公共子序列(LCS).最大子序列和等,那么首先我们从这几个经典的问题出发开始对线性dp的探索. 首先我们来看最长上升子序列问题. 这个问题基于这样一个背景,对于含有n个元素的集合S = {a1.a2.a3……an},对于S的一个子序列S‘ = {ai,aj,ak