• 2021.06.19 DP-方格取数 + 花店橱窗布置


    T1

    方格取数

    题意

    (A_{i,j})内找到从(A_{1,1})(A_{n,n})的两条路径,使两条路径权值和最大

    分析

    一道比较经典的题。
    先考虑只有一条路径的情况。
    不难发现,有(dp[i][j]=max{dp[i-1][j],dp[i][j-1]}+a[i][j])(由左/上转移过来)
    考虑两条路径的情况:
    可以再开两维,([k][p])的后两维表示另一条路径走到((k,p))的权值。
    :因为两条道路不能重合,所以写为:if(i != k && j != q) dp[i][j][k][q] += a[k][q];(如果两个不在同一点,则加上新点的权值)

    相似题目:传纸条

    代码

    #include <bits/stdc++.h>
    #define fo(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout)
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const int INF = 0x3f3f3f3f , N = 15;
    inline ll read(){
    	ll ret = 0 ; char ch = ' ' , c = getchar();
    	while(!(c >= '0' && c <= '9'))ch = c , c = getchar();
    	while(c >= '0' && c <= '9')ret = (ret << 1) + (ret << 3) + c - '0' , c = getchar();
    	return ch == '-' ? -ret : ret;
    }
    int a[15][15],n;
    int dp[N][N][N][N];
    inline int Max(int a,int b,int c,int d){return max(max(a,b),max(c,d));}
    signed main(){
    	n = read();
    	while(1){
    		int x = read() , y = read() , p = read();
    		if(!x && !y)break; 
    		a[x][y] = p;
    	}
    	for(int i = 1 ; i <= n ; i ++)
    		for(int j = 1 ; j <= n ; j ++)
    			printf("%d%c",a[i][j]," 
    "[j==n]); 
    	for(int i = 1 ; i <= n ; i ++)
    		for(int j = 1 ; j <= n ; j ++)
    			for(int k = 1 ; k <= n ; k ++)
    				for(int q = 1 ; q <= n ; q ++){
    						dp[i][j][k][q] = max(dp[i][j][k][q],Max(dp[i-1][j][k-1][q],dp[i-1][j][k][q-1],dp[i][j-1][k-1][q],dp[i][j-1][k][q-1])+a[i][j]);
    						if(i != k && j != q) dp[i][j][k][q] += a[k][q];
    				}
    	printf("%d",dp[n][n][n][n]);
    	return 0;
    }
    

    T2

    花店橱窗布置

    题意

    给定(A_{n,m})的矩阵,找到(forall 1 < i le n且1le k < j le m,A_{i-1,k} o A_{i,j})的路径权值最大的,并输出路径

    分析

    同前,易得到(dp[i][j] = dp[i-1][k] + a[i][j])
    记录一下路径并输出即可。

    1. 因为会选取到((1,1)),而"正常的DP"中不会遍历到这一点,导致错误!!->k从0开始枚举
    2. 因为数据可能是负值,所以memset()需要赋为(-infty)

    代码

    #include <bits/stdc++.h>
    #define fo(a) freopen(a".in","r",stdin)//,freopen(a".out","w",stdout)
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const int INF = 0x3f3f3f3f , N = 105;
    inline ll read(){
    	ll ret = 0 ; char ch = ' ' , c = getchar();
    	while(!(c >= '0' && c <= '9'))ch = c , c = getchar();
    	while(c >= '0' && c <= '9')ret = (ret << 1) + (ret << 3) + c - '0' , c = getchar();
    	return ch == '-' ? -ret : ret;
    }
    int n,m;
    int a[N][N],dp[N][N],pre[N][N];
    void print(int i,int j){
    	if(!i)return;
    	print(i-1,pre[i][j]);
    	printf("%d ",j);
    }
    signed main(){
    //	fo("a");
    	memset(dp,-0x3f,sizeof(dp));
    	n = read() , m = read();
    	for(int i = 1 ; i <= n ; i ++)
    		for(int j = 1 ; j <= m ; j ++)
    			a[i][j] = read();
    	for(int i = 0 ; i <= m ; i ++)
    		dp[0][i] = 0;
    	for(int i = 1 ; i <= n ; i ++)
    		for(int j = i ; j <= m - n + i ; j ++)
    			for(int k = 0 ; k < j ; k ++)
    				if(dp[i][j] < dp[i-1][k] + a[i][j])
    					dp[i][j] = dp[i-1][k] + a[i][j],
    					pre[i][j] = k;
    	int maxn = -INF,pos;
    	for(int i = 1 ; i <= m ; i ++)
    		if(maxn < dp[n][i])
    			maxn = dp[n][i],pos = i;
    	printf("%d
    ",maxn);
    	print(n,pos);
    	return 0;
    }
    
  • 相关阅读:
    Object有哪些方法?
    去除掉myeclipse2017页面右上角的图片
    报错 IllegalArgumentException occurred calling getter of cn.itcast.entity.Customer.cid
    如果在applicationContext.xml中没有配置bean的属性,那么也会导致空指针异常
    报错HTTP Status 500
    srm开发(基于ssh)(4)
    报错HTTP Status 500
    HTTP Status 500
    数字
    算法总结——树状数组
  • 原文地址:https://www.cnblogs.com/Shinomiya/p/14904645.html
Copyright © 2020-2023  润新知