hdu 1876 dp

看到网上解法太多,感觉有点乱,其实就是水dp一枚,搞清递推过程就行了;

dp【i】【j】【k】k=0表示到达(i,j)这个点最多的完全消耗能量,k1小时种数,其中(i,j)这些点不是全部点,而是到达这个点能量正好为0的点或中点;

leap【】【】用来标记这些点,在跑的过程中就只跑这些点;

递推公式为

if(dp[i][j][0]+1==dp[x][y][0]) dp[x][y][1]+=dp[i][j][1];

else if(dp[i][j][0]+1>dp[x][y][0])

{

dp[x][y][0]=dp[i][j][0]+1;

dp[x][y][1]=dp[i][j][1];

}

对中点要特判下就行;

#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;

int max(int a,int b)
{
    return a>b?a:b;
}
int min(int a,int b)
{
    return a<b?a:b;
}
int n,m;
int judge(int x,int y)
{
    if(x>n||y>m) return 0;
    return 1;
}
int main()
{
    int i,j,T;
    int map[110][110],leap[110][110];
    int dp[110][110][2];
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=m;j++)
            scanf("%d",&map[i][j]);
        }
        memset(dp,0,sizeof(dp));
        memset(leap,-1,sizeof(leap));
        dp[1][1][0]=0;
        dp[1][1][1]=1;
        leap[1][1]=0;
        for(i=1;i<=n;i++)
        for(j=1;j<=m;j++)
        {
            if(map[i][j]==0) continue;
            if(leap[i][j]>=0)
            {
                int t=map[i][j];
                //printf("$$$%d\n",t);
                if(n-i+m-j<t)
                {
                    if(dp[i][j][0]==dp[n][m][0]) dp[n][m][1]+=dp[i][j][1];
                    else if(dp[i][j][0]>dp[n][m][0])
                    {
                        dp[n][m][0]=dp[i][j][0];
                        dp[n][m][1]=dp[i][j][1];
                    }
                }
                else if(n-i+m-j==t)
                {
                    if(dp[i][j][0]+1==dp[n][m][0]) dp[n][m][1]+=dp[i][j][1];
                    else if(dp[i][j][0]+1>dp[n][m][0])
                    {
                        dp[n][m][0]=dp[i][j][0]+1;
                        dp[n][m][1]=dp[i][j][1];
                    }
                }
                else
                {
                    for(int k=0;k<=t;k++)
                    {
                        int x=i+k;
                        int y=j+t-k;
                        if(!judge(x,y)) continue;
                        leap[x][y]=1;
                        if(dp[i][j][0]+1==dp[x][y][0]) dp[x][y][1]+=dp[i][j][1];
                        else if(dp[i][j][0]+1>dp[x][y][0])
                        {
                            dp[x][y][0]=dp[i][j][0]+1;
                            dp[x][y][1]=dp[i][j][1];
                        }
                    }
                }
            }
        }
        printf("%d %d\n",dp[n][m][0],dp[n][m][1]);
    }
    return 0;
}
时间: 2024-11-17 02:25:28

hdu 1876 dp的相关文章

HDU 4832(DP+计数问题)

HDU 4832 Chess 思路:把行列的情况分别dp求出来,然后枚举行用几行,竖用几行,然后相乘累加起来就是答案 代码: #include <stdio.h> #include <string.h> #include <iostream> using namespace std; typedef long long ll; const ll MOD = 9999991; const int N = 1005; int t, n, m, k, x, y; ll dp1

hdu 3944 dp?

DP? Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 128000/128000 K (Java/Others)Total Submission(s): 1804    Accepted Submission(s): 595 Problem Description Figure 1 shows the Yang Hui Triangle. We number the row from top to bottom 0,1,2,-a

hdu 5389 dp类似背包

http://acm.hdu.edu.cn/showproblem.php?pid=5389 Problem Description Zero Escape, is a visual novel adventure video game directed by Kotaro Uchikoshi (you may hear about ever17?) and developed by Chunsoft. Stilwell is enjoying the first chapter of this

hdu 1025 dp 最长上升子序列

1 //Accepted 4372 KB 140 ms 2 //dp 最长上升子序列 nlogn 3 #include <cstdio> 4 #include <cstring> 5 #include <iostream> 6 using namespace std; 7 const int imax_n = 500005; 8 int dp[imax_n]; 9 int d[imax_n]; 10 int a[imax_n]; 11 int n; 12 int len

HDU 5928 DP 凸包graham

给出点集,和不大于L长的绳子,问能包裹住的最多点数. 考虑每个点都作为左下角的起点跑一遍极角序求凸包,求的过程中用DP记录当前以j为当前末端为结束的的最小长度,其中一维作为背包的是凸包内侧点的数量.也就是 dp[j][k]代表当前链末端为j,其内部点包括边界数量为k的最小长度.这样最后得到的一定是最优的凸包. 然后就是要注意要dp[j][k]的值不能超过L,每跑一次凸包,求个最大的点数量就好了. 和DP结合的计算几何题,主要考虑DP怎么搞 /** @Date : 2017-09-27 17:27

HDU 4901 DP背包

给你n个数,问你将数分成两个数组,S,T ,T 中所有元素的需要都比S任意一个大,问你S中所有元素进行 XOR 操作和 T 中所有元素进行 &操作值相等的情况有多少种. DP背包思路 dpa[i][j][0]  表示从左开始到i,不取i,状态为j的方案数 dpa[i][j][1]  表示从作开始到i,取i,状态为j的方案数 dpb[i][j]      表示从右开始到i,状态为j的方案数 因为S集合一定在T集合的左边,那么可以枚举集合的分割线,并且枚举出的方案要保证没有重复,如果要保证不重复,只

Bone Collector II(HDU 2639 DP)

Bone Collector II Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3471    Accepted Submission(s): 1792 Problem Description The title of this problem is familiar,isn't it?yeah,if you had took par

hdu 4472 dp

http://acm.hdu.edu.cn/showproblem.php?pid=4472 第一直觉找规律,第二直觉 把树拆成子树,然后递推或者DP 然后发现不行,然后才发现自己题都没读,,,, dp[i]=segma(dp[j] | (i-1)%j==0) #include <cstdio> #include <cstring> #include <cstring> const int MAXN = 1000+50; const int MOD = 1e9+7; #

hdu 5791 (DP) Two

hdu 5791 Two Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1421    Accepted Submission(s): 630 Problem Description Alice gets two sequences A and B. A easy problem comes. How many pair of sequ