hdu1176(二维dp思路讲解)(详细注释)

没听说过二维dp前根本想不出来啊!!!!
下面附上老师结合本题对二维dp讲解:
通常而言,如果用1个整数状态的方程 写不出来,就用2个整数,也就是升维
•2个写不出来,就用3个,以此类推
•但是升维会严重消耗时空,通常需要 结合数据范围来进行判定:
•到底是应该升维还是需要寻找更巧妙 的状态表示与规划目标
•在接馅饼这道题中,馅饼的数量显然 与位置也有关
•因此这道题的状态要用2个数表示,目 标记作Dtx,Dtx表示在t时刻、x位置能 够接到的最大数量

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#define MAXN 100010
using namespace std;

int dp[MAXN][12],pile[MAXN][12];

///全局变量和静态变量的存储区域是在一起的,程序结束后由系统释放。数据区的大小由系统限定,一般很大。

int max_is(int a,int b,int c);

int main(){

    int n,x,t,i,j,maxt;

    while(scanf("%d",&n)!=EOF&&n){

        memset(dp,0,sizeof(dp));

        memset(pile,0,sizeof(pile));

        maxt=0;

        for(i=0;i<n;i++){

            scanf("%d%d",&x,&t);

            pile[t][x]++;

            if(maxt<t) maxt=t;

        }

        for(i=1;i<=11;i++)

            dp[maxt][i]=pile[maxt][i];//移动结束的时候的时间总是最晚的那个馅饼落下的时间

        for(i=maxt-1;i>=0;i--)//最晚时刻在上面循环的初始化好了,从最晚时刻前面一秒开始dp到时间为0的地方,即dp【0】【5】
        {

            for(j=0;j<11;j++)
                {

                if(j==0) dp[i][j]=max(dp[i+1][j],dp[i+1][j+1])+pile[i][j];//处理在边界的特殊情况

                else dp[i][j]=max_is(dp[i+1][j-1],dp[i+1][j],dp[i+1][j+1])+pile[i][j];/*一般情况怎么dp。i时间,j位置。
                后面的状态无非是前面的左移1,右移1,不动三种操作中的一种得到,取max再加上该点掉的馅饼*/

                }

        }

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

    }

    return 0;

}

int max_is(int a,int b,int c){

    return max(a,max(b,c));

}

到这篇博客,我半个月刷的代表性题目也贴完了,最后还是因为种种原因 (就是菜) 放弃了acm。
其实做这些题大部分都参考了别人的思路和代码,甚至有些就是理解后再背着敲出来的,但还是会有些错误自己debug了很久,综上感觉可能自己真的不太适合acm吧,但每次ac带来的感动我也体验过了hhhh。以后还是会有算法题的博客的,当然可能都会是些不太难比较适合非acmer的算法题了,我也会保持我的带有自我理解的详细注释的(虽然自己感觉清楚,但是可能别人都看不懂我再说啥hhhh,表达也是门功夫啊),业余刷刷简单算法也不错嘛。就酱,再见。

发布了30 篇原创文章 · 获赞 5 · 访问量 6941

猜你喜欢

转载自blog.csdn.net/weixin_44735312/article/details/90957047