zoukankan      html  css  js  c++  java
  • 多维dp

    P1006 传纸条 我的第一道多维dp

    我第一眼看到这道题 就知道不会 因为从来没见过 

    后来看了神仙的题解 恍然大悟 然而自己写的时候还是有bug(逃

    这里给出一个三维数组的解法(oi爷太强了

    首先,要找来回两条路径,这样考虑太麻烦,把它转化为两个人从1,1这点一起走,一直走到n,m这点所经过的路径。

    定义dp[p][i][j]表示当前走了p步,第一个人走到第i行,第二个人走到第j行的最大价值。

    显然两个人的坐标都可以计算出来,第一个人是(i,p-i+1),第二个人是(j,p-j+1).

    那么状态转移方程呼之欲出 就是

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

    不要以为到这就结束了!

    在循环时 我们一定要判断!!

    判断什么呢 当i=j时 代表他们坐标重复了(想想为什么   所以这时候 价值只能算i j其中一个的

    还有一点! 循环时 双层循环全部要到m 而不是一个n一个m  因为这里的 i j 全部代表层数 

    还有一点(我wa掉的一点   就是双层for不仅要判断层数小于m 而且要判断当前步数小于总步数

    要不然会wa掉第二个点(逃

    接下来 放代码

    #define rep(i,a,b) for(int i=a;i<=b;i++)
    #include <stdio.h>
    #include <iostream>
    using namespace std;
    const int e=55;
    int dp[2*e][e][e],num[e][e];
    int n,m;
    int maxx(int a,int b,int c,int d)
    {
    	if(a<b)
    		a=b;
    	if(c>a)
    		a=c;
    	if(d>a)
    		a=d;
    	return a;
    }
    int main(int argc, char const *argv[])
    {
    	cin >> m >> n;
    	rep(i,1,m){
    		rep(j,1,n){
    			cin >> num[i][j];
    		}
    	}
    	dp[1][1][1]=num[1][1];
    	rep(p,2,n+m-1){
    		for(int i=1;i<=m&&i<=p;i++){
    			for(int j=1;j<=m&&j<=p;j++){
    				dp[p][i][j]=maxx(dp[p-1][i][j],dp[p-1][i-1][j-1],dp[p-1][i][j-1],dp[p-1][i-1][j]);
    				int sum;
    				if(i==j)
    					sum=num[j][p-j+1];
    				else
    					sum=num[i][p-i+1]+num[j][p-j+1];
    				dp[p][i][j]+=sum;
    			}
    		}
    	}
    	printf("%d
    ", dp[n+m-1][m][m]);
    	return 0;
    }
    

      

     

    人十我百 人百我万
  • 相关阅读:
    PRISM概率模型检测器初使用--骰子模型(改进版)
    什么是P问题、NP问题和NPC问题
    kali linux进行arp欺骗和dos攻击
    java log日志的输出。
    sublime text3输入中文的问题.
    java 正则表达式匹配字符串
    python tornado+mongodb的使用
    jasper3
    jasper2
    jasper
  • 原文地址:https://www.cnblogs.com/bestcoder-Yurnero/p/10719065.html
Copyright © 2011-2022 走看看