hdu2084数塔&&hdu1176免费馅饼&&hdu2571命运——数字三角形问题

特征是只能从相邻的走过来

hdu2084数塔

题意:要求从顶层走到底层,若每一步只能走到相邻的结点,则经过的结点的数字之和最大是多少?

dp[i][j]+=max\left \{ dp[i+1][j],dp[i+1][j+1] \right \}

从上往下可能性太多不好做,从下往上更新每个点只由两个点更新

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

int d[110][110];                             //dp[i][j]代表i,j位置可获得的最大值

int n;


int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;++i)
            for(int j=1;j<=i;++j)
            scanf("%d",&d[i][j]);
        for(int i=n-1;i>=1;--i)
            for(int j=1;j<=i;++j)
            d[i][j]+=max(d[i+1][j],d[i+1][j+1]);
        printf("%d\n",d[1][1]);
    }
    return 0;

}

hdu 1176免费的馅饼

题意:在一个数轴上,指定一个起始位置,每次移动只能向左或右一个单位,或者不移动。总共n个馅饼,第T秒有一个馅饼掉在x点上,同一秒钟在同一点上可能掉下多个馅饼。问最多能接到几个馅饼

dp[i][j]+=max(dp[i+1][j],max(dp[i+1][j-1],dp[i+1][j+1]))

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
//只能从相邻的地方过来和数塔很像
int dp[100010][15];                             //d[i]代表第i层的最大值
                                                //怎么把一开始在5这个条件加上去   倒着算
const int INF=0x3f3f3f3f;
int n;
int t,x;
int main()
{
    while(scanf("%d",&n)!=EOF&&n)
    {
        memset(dp,0,sizeof(dp));
        int T=0;
        for(int i=1;i<=n;++i)
        {
            scanf("%d%d",&x,&t);                //把x,t读反了啊啊啊啊
            T=max(T,t);
            dp[t][x]+=1;
        }



        for(int i=T-1;i>=0;--i)
            for(int j=0;j<11;++j)
            {
                if(j==0)
                    dp[i][j]+=max(dp[i+1][j],dp[i+1][j+1]);
                else
                    dp[i][j]+=max(dp[i+1][j],max(dp[i+1][j-1],dp[i+1][j+1]));
            }
        printf("%d\n",dp[0][5]);
    }
    return 0;

}

hdu2571 命运

题意:yifenfei起始在(1,1)位置,魔王在(n,m)位置,如果当前格子是(x,y),下一步可以是(x+1,y),(x,y+1)或者(x,y*k) 其中k>1。每个格子有个幸运值,怎么走才能得到最大的幸运值

不过他没有很明显的时间序,所以顺着走

1、数值有负数,初始化的地方要注意

2、在整数倍的地方考虑不周

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
//只能从相邻的地方过来和数塔很像
int dp[25][1010];                   //dp[i][j] 在第i行第j列所能获得的最大的
const int INF=0x3f3f3f3f;
int n;
int t,x;

int main()
{
    int c;
    scanf("%d",&c);
    while(c--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j)
            scanf("%d",&dp[i][j]);
        for(int i=0;i<=n;++i)
            dp[i][0]=-INF;
        for(int j=0;j<=m;++j)
            dp[0][j]=-INF;
        dp[0][1]=dp[1][0]=0;
        //没有初始化是错的
        for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j)
            {
                int tmp=-INF;               //初始化错误
//                if(i-1)                     //如果不是第一行
//                    tmp=max(tmp,dp[i-1][j]);
//                if(j-1)                     //如果不是第一列
//                    tmp=max(tmp,dp[i][j-1]);
                tmp=max(dp[i-1][j],dp[i][j-1]);
                for(int k=2;k<=m;++k)       // k=1(1,1)这里就是双倍  k也不能为j
                {
                    if(!(j%k))              //原先写的dp[i][k]那么就永远无法从1转移过来
                        tmp=max(tmp,dp[i][j/k]);
                }
                dp[i][j]+=tmp;
            }


        printf("%d\n",dp[n][m]);

    }
    return 0;

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值