第一次做树型DP。。。。。感觉听说了很长时间了,一直以为很难。。。但是这题比想象中的简单多了。可能是因为运气比较好,一开始就在正确是思路上?
这道题的主要解题思路有点类似于背包问题,先把问题简化,当需要解决的问题是一个没有分叉的走廊的话,可以很容易得到在限制条件s为不同值的最优解。
然后考虑有分叉的情况,如果使用类似于背包问题的方式,把一个走廊分叉到两个走廊之后得到的答案用数组a,b表示,那么只需要考虑如何将它们组合成本走廊的最优解即可。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef int Lint[620];
int cnt = 0;
void combine(int *a,int *b,int L,int *list,int s){
int i, j, k;
for (i = 0; i <= s; i++){
for (j = 0,k = i + j + L * 2; j + i + L * 2<= s; j++,k++){
list[k] = max(a[i] + b[j], list[k]);
}
}
return;
}
void DFSsolve(int *list, const int s){
int L,N,i,j,k;
scanf("%d %d", &L,&N);
if (N == 0){
Lint a, b;
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
DFSsolve(a, s);
DFSsolve(b, s);
combine(a, b, L,list,s);
}
else{
for (i = L * 2 + 5; i <= s; i++){
list[i] = min( N ,(i - 2 * L) / 5);
}
}
}
int main(){
int s;
while (cin >> s){
Lint L;
memset(L, 0, sizeof(L));
DFSsolve(L, s);
cout << L[s] << endl;
}
return 0;
}