题目大意:
给你n*m的矩形(m >= n)
每个节点mp[i][j]有一个权值,从第一行走到最后一行,每一行只准选择一个数且对于i行,所选数的列数要严格大于i-1行选择的列数
问你最大权值是多少,并输出选择的n个列数
思路:
DP方程非常好想:DP[i][j] = max(DP[i][j - 1], DP[i - 1][j - 1] + mp[i][j]);
找路径的话,可以每行可以从从i+1到m,也可以直接从i - 1开始找
也可以在DP里面做标记,状态转移的时候将此点记录!
但是不能想的太无脑,你懂的
附上代码;
#include <iostream> #include <stdio.h> #include <algorithm> #include <string.h> #include <string> #include <math.h> #include <stack> #include <queue> #include <vector> #include <map> #include <set> #pragma warning(disable:4996) #define Zero(a) memset(a, 0, sizeof(a)) #define Neg(a) memset(a, -1, sizeof(a)) #define All(a) a.begin(), a.end() #define PB push_back #define repf(i,a,b) for(int i = a;i <= b; i++) #define repff(i,a,b) for(int i = a; i < b; ++i) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define root 1,n,1 #define ld rt << 1 #define rd rt << 1 | 1 #define ll long long #define MAXN 105 #define INF 0x3f3f3f3f #define mod 10007 using namespace std; vector<int>go; int n, m, dp[MAXN][MAXN], gg[MAXN][MAXN], mp[MAXN][MAXN]; void init(){ memset(gg, 0, sizeof(gg)); for (int i = 1; i <= n; ++i) for (int j = 1; j <= m; ++j){ scanf("%d", &mp[i][j]); if(i != 0)dp[i][j] = -INF; else dp[i][j] = 0; } for (int i = 0; i <= n; ++i) for (int j = 0; j <= m; ++j){ if (i != 0)dp[i][j] = -INF; else dp[i][j] = 0; } go.clear(); } int main(){ while (~scanf("%d%d", &n, &m)){ init(); for (int i = 1; i <= n; ++i) for (int j = 1; j <= m; ++j){ if (dp[i - 1][j - 1] + mp[i][j] > dp[i][j - 1]){ gg[i][j] = 1; //cout << "go" << endl; dp[i][j] = dp[i - 1][j - 1] + mp[i][j]; } else{ dp[i][j] = dp[i][j - 1]; } } printf("%d\n", dp[n][m]); int nowx = n,nowy = m; while (nowx && nowy){ if (gg[nowx][nowy] == 1){ go.push_back(nowy); nowx--; nowy--; } else{ nowy--; } } int len = go.size(); for (int i = len - 1; i >= 0; --i){ if (i != len - 1) printf(" "); printf("%d", go[i]); } puts(""); } return 0; }
时间: 2024-10-14 23:18:17