Description
Students who love electronic entertainment must be familiar with the skill tree. That is, to learn low-level garbage skills, specific
A few garbage skills learned to learn stronger skills. For example, to learn the inferno and the fire wall first.
Blaze. The same is true of technology trees. It is necessary to study the power and the internal combustion engine before we can study industrial science. So now we're simplifying the problem,
This is a skill tree (or technology tree). The number on the grid is the power value. To learn the first row of the second and third, to
Learn the second of the second row. The prerequisites for each skill study are the top left and top two skills. Suppose there is now a first
Layer has n skills of the skill tree, and the skill point is limited, can only learn m skills, we want to know the maximum power value
The sum of the sum is how much.
(PS: This is not a sample) Input Format
The first line is two numbers n and M, as described in title
After n rows, line I, there are n+1-i number. Represents a skill tree. Output Format
Outputs a number that represents the sum of the maximum power values of Sample Input
4 5
1 1 1 1
1 2 1
1 1
1 Sample Output
6 Data Limit
For 40% of data, n<=10
For 100% of the data, n<=50,m<=500, all data is within Int.
The DP on the
skill tree is an easy-to-think DP problem, because this tree-like structure of DP everyone is very familiar with, get this problem is easy to think of as a tree gauge or from the top down, from the bottom of the DP problem, but see this problem data range is so small, a look at the problem, Then it got stuck and ended up writing only one o (2n) O (2^n) of violence.
So now let's take a closer look at this problem because the DP has no effect (the current state is only related to the previous state, and the previous state does not affect the current state, and the current state can only affect the state behind it, not the state behind it), And if we are from the top down DP, can not go to a certain number must see it above the umbrella structure of the part take no, completely unable to normal DP, the equation has been listed.
Let's start thinking about how our DP achieves no-effect.
Look closely we can see that no matter how we take it, the contour line is a jagged polyline.
We find that each column has only one point on the contour line, and these are the points we can use for DP.
We consider a left-to-right DP, where each point above the contour can have only the top or bottom of its previous column, and it is not valid for DP
as shown above, we set "14" in the first row, " 33 "In the second row, the second column, password" 15 "in the first row, the third column,
and if you take a point, it means that to take all the points above it, we can first preprocess the number of points on each point in the presence of num array, value and existence sum array, f[k][i] [j] means that the [i][j] contour line takes this coordinate, takes the maximum number of K, and then begins the state transition.
F[k][i][j]=max (f[k−num[i][j]][i−1][j−1],f[k−num[i][j]][i+1][j−1]) +sum[i][j] F[k][i][j]=max (f[k-num I [J]] [I-1] [j-1],f[k-num[i][j]][i+1][j-1]) +sum[i][j]
Then there is a situation is to note that it is possible that the contour line is not continuous, the previous paragraph, the following paragraph, then we have to deal with the No. 0 row of the case, the No. 0 line of the DP when the state is a 0 line before it and it above the previous 1th line DP come over, namely:
F[k][0][j]=max (f[k][0][j−2],f[k][1][j−1]) F[k][0][j]=max (F[k][0][j-2],f[k][1][j-1])
This is probably the case, and then my program in the following, but, has been WA a point, it is not changed out _ (: Зゝ∠), or sent up as a reference bar.
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #define M-Using
namespace Std;
int a[m][m],sum[m][m],num[m][m],f[m*5][m][m],n,m;
int main () {cin>>n>>m;
for (int i=1;i<=n;i++) for (int j=i;j<=2*n-i;j+=2) scanf ("%d", &a[i][j]);
for (int i=1;i<=n;i++) for (int j=1;j<=2*n-1;j++) {sum[i][j]=sum[i-2][j]+a[i][j];
NUM[I][J]=NUM[I-1][J];
if (A[i][j]) num[i][j]++;
} for (int i=1;i<=n*2-1;i+=2) {f[1][1][i]=a[1][i];
F[1][0][i+1]=max (F[1][0][i-1],f[1][1][i]); } for (int k=2;k<=m;k++) for (int. j=1;j<=2*n-1;j++) for (int i= (j%2==0?0:1); I<=n-abs (n-j); I +=2) {if (i==0) {F[k][i][j]=max (f[k][0][j-2],f[k][1][j-1]
);
Continue } if (k-num[i][j]<0| | (f[k-num[i][j]][i-1][j-1]==0&&f[k-num[i][j]][i+1][j-1]==0)) continue;
F[k][i][j]=max (F[k-num[i][j]][i-1][j-1],f[k-num[i][j]][i+1][j-1]) +sum[i][j];
} int ans=0;
for (int i=1;i<=2*n-1;i++) Ans=max (Ans,f[m][1][i]);
cout<<ans;
return 0; }
If there is any problem, or error, please ask in the comment area, thank you.