hdu1208 dp

题意:给了一个 n * n 的方格图,要从图的左上角走到右下角 ,每次只能向右或者向下走,走的格数为当前格子上的数字,问共有多少中走法。

一开始我看到之后觉得这题完全可以用记忆化搜索来做,dfs 一遍就能找出所有解,这是因为刚刚不久才做过那道记忆化搜索的题目,我用 dp + dfs 敲了一遍之后作死提交,果断AC```怎么可能想想都知道```TLE了,恩其实题目底下就有提示说是遍历所有的路可能会超时,但是我英语不好 orz 。

但事实上即使没有这个提示我也本就应该先考虑普通 DP ,因为上次的记忆化搜索是因为那张图是可以往上下左右四个方向走的,所以普通的顺序 dp 就会面临更新完别的格子之后自己又要更新的情况,但是这次只有向右和向下,所以完全应该第一个想到顺序 dp 的,这是我自己想复杂的,当然也要归咎于我对 dp 和记忆化搜索理解的还不够到位吧。

那么顺序的 dp 其实就非常简单了,dp [ i ] [ j ] 表示走到第( i , j )格的走法数, dp [ 1 ] [ 1 ] 是开始位置,所以标记为 1 ,之后依次遍历每一个点,如果该点 dp 值不为 0 ,即该点可以被走到 ,那么就根据它格子上的数字优化能从这个格点到达的格子的 dp 值。当然,要注意的是当格点数字为 0 的时候就不要对自己进行更新了,因为这样若右下角格子的数字是 0 的话,它就会连续优化自己,与其特判还不如一开始就不操作。优化方式就是将能到达的格点的 dp 值加上当前点的 dp 值。

 1 #include<stdio.h>
 2 #include<string.h>
 3 int a[35][35];
 4 long long dp[35][35];
 5 int xx[2]={1,0};
 6 int yy[2]={0,1};
 7 int main(){
 8     int n;
 9     while(scanf("%d",&n)!=EOF&&n!=-1){
10         getchar();
11         memset(dp,0,sizeof(dp));
12         int i,j;
13         dp[1][1]=1;
14         for(i=1;i<=n;i++){
15             for(j=1;j<=n;j++){
16                 char m;
17                 scanf("%c",&m);
18                 a[i][j]=m-‘0‘;
19                 if(a[i][j]){
20                     if(dp[i][j]){
21                         int dx=i+a[i][j]*xx[0],dy=j+a[i][j]*yy[0];
22                         if(dx<=n&&dy<=n)dp[dx][dy]+=dp[i][j];
23                         dx=i+a[i][j]*xx[1];dy=j+a[i][j]*yy[1];
24                         if(dx<=n&&dy<=n)dp[dx][dy]+=dp[i][j];
25                     }
26                 }
27             }
28             getchar();
29         }
30 /*        for(i=1;i<=n;i++){
31             for(j=1;j<=n;j++){
32                 printf("%d ",dp[i][j]);
33             }
34             printf("\n");
35         }*/
36         printf("%I64d\n",dp[n][n]);
37     }
38     return 0;
39 }

时间: 2024-12-15 08:42:54

hdu1208 dp的相关文章

HDU 5542 The Battle of Chibi dp+树状数组

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5542 题意:给你n个数,求其中上升子序列长度为m的个数 可以考虑用dp[i][j]表示以a[i]结尾的长度为j的上升子序列有多少 裸的dp是o(n2m) 所以需要优化 我们可以发现dp的第3维是找比它小的数,那么就可以用树状数组来找 这样就可以降低复杂度 #include<iostream> #include<cstdio> #include<cstring> #include

hdu 1207 汉诺塔II (DP+递推)

汉诺塔II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4529    Accepted Submission(s): 2231 Problem Description 经典的汉诺塔问题经常作为一个递归的经典例题存在.可能有人并不知道汉诺塔问题的典故.汉诺塔来源于印度传说的一个故事,上帝创造世界时作了三根金刚石柱子,在一根柱子上从下往

POJ - 3186 Treats for the Cows (区间DP)

题目链接:http://poj.org/problem?id=3186 题意:给定一组序列,取n次,每次可以取序列最前面的数或最后面的数,第n次出来就乘n,然后求和的最大值. 题解:用dp[i][j]表示i~j区间和的最大值,然后根据这个状态可以从删前和删后转移过来,推出状态转移方程: dp[i][j]=max(dp[i+1][j]+value[i]*k,dp[i][j-1]+value[j]*k) 1 #include <iostream> 2 #include <algorithm&

51Nod 1009 数字1的个数 | 数位DP

题意: 小于等于n的所有数中1的出现次数 分析: 数位DP 预处理dp[i][j]存 从1~以j开头的i位数中有几个1,那么转移方程为: if(j == 1) dp[i][j] = dp[i-1][9]*2+pow(10,i-1);else dp[i][j] = dp[i-1][9]+dp[i][j-1]; 然后注意下对于每个询问统计的时候如果当前位为1需要额外加上他后面所有位数的个数,就是n%pow(10,i-1); 这样总复杂度log(n)*10 #include <bits/stdc++.

HDU 3555 Bomb (数位DP)

数位dp,主要用来解决统计满足某类特殊关系或有某些特点的区间内的数的个数,它是按位来进行计数统计的,可以保存子状态,速度较快.数位dp做多了后,套路基本上都差不多,关键把要保存的状态给抽象出来,保存下来. 简介: 顾名思义,所谓的数位DP就是按照数字的个,十,百,千--位数进行的DP.数位DP的题目有着非常明显的性质: 询问[l,r]的区间内,有多少的数字满足某个性质 做法根据前缀和的思想,求出[0,l-1]和[0,r]中满足性质的数的个数,然后相减即可. 算法核心: 关于数位DP,貌似写法还是

Codeforces Round #286 (Div. 1) A. Mr. Kitayuta, the Treasure Hunter DP

链接: http://codeforces.com/problemset/problem/506/A 题意: 给出30000个岛,有n个宝石分布在上面,第一步到d位置,每次走的距离与上一步的差距不大于1,问走完一路最多捡到多少块宝石. 题解: 容易想到DP,dp[i][j]表示到达 i 处,现在步长为 j 时最多收集到的财富,转移也不难,cnt[i]表示 i 处的财富. dp[i+step-1] = max(dp[i+step-1],dp[i][j]+cnt[i+step+1]) dp[i+st

bzoj1801: [Ahoi2009]chess 中国象棋 [dp]

Description 在N行M列的棋盘上,放若干个炮可以是0个,使得没有任何一个炮可以攻击另一个炮. 请问有多少种放置方法,中国像棋中炮的行走方式大家应该很清楚吧. Input 一行包含两个整数N,M,中间用空格分开. Output 输出所有的方案数,由于值比较大,输出其mod 9999973 Sample Input 1 3 Sample Output 7 HINT 除了在3个格子中都放满炮的的情况外,其它的都可以. 100%的数据中N,M不超过10050%的数据中,N,M至少有一个数不超过

状压DP问题

状态压缩·一 题目传送:#1044 : 状态压缩·一 AC代码: #include <map> #include <set> #include <list> #include <cmath> #include <deque> #include <queue> #include <stack> #include <bitset> #include <cctype> #include <cstdi

Educational Codeforces Round 21 G. Anthem of Berland(dp+kmp)

题目链接:Educational Codeforces Round 21 G. Anthem of Berland 题意: 给你两个字符串,第一个字符串包含问号,问号可以变成任意字符串. 问你第一个字符串最多包含多少个第二个字符串. 题解: 考虑dp[i][j],表示当前考虑到第一个串的第i位,已经匹配到第二个字符串的第j位. 这样的话复杂度为26*n*m*O(fail). fail可以用kmp进行预处理,将26个字母全部处理出来,这样复杂度就变成了26*n*m. 状态转移看代码(就是一个kmp