Description
Input
Output
Sample Input
2 1 0 11 1 2 3 2 0 1 2 1 2 1 3
Sample Output
11 2
Source
POJ Contest,Author:magicpig@ZSU
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
树形DP~
因为走到一个叶子节点后要原路返回才能走到下一个节点,所以记录的f数组要多加一维状态记录是否会返回该点,则f[i][j][k]就表示从点i向子节点走了j步,如果k==1,则表示没有回到该点,k==0则表示回到该点。
状态转移方程就是f[u][i][1]=max(f[u][i][1],f[u][i-j][0]+f[kkz][j-1][1]);
f[u][i][1]=max(f[u][i][1],f[u][i-j][1]+f[kkz][j-2][0]);
f[u][i][0]=max(f[u][i][0],f[u][i-j][0]+f[kkz][j-2][0]);
(f数组不能开太大,否则会T的。)
#include
#include
#include
using namespace std;
int n,k,x,y,akz,w[10001],ne[10001],fi[10001],fa[10001],f[101][201][2],cnt;
void add(int u,int v)
{
w[++cnt]=v;ne[cnt]=fi[u];fi[u]=cnt;
}
void findd(int u)
{
for(int kkzv=fi[u];kkzv;kkzv=ne[kkzv])
if(w[kkzv]!=fa[u])
{
int kkz=w[kkzv];fa[kkz]=u;
findd(kkz);
for(int i=k;i>=1;i--)
for(int j=1;j<=i;j++)
{
f[u][i][1]=max(f[u][i][1],f[u][i-j][0]+f[kkz][j-1][1]);
f[u][i][1]=max(f[u][i][1],f[u][i-j][1]+f[kkz][j-2][0]);
f[u][i][0]=max(f[u][i][0],f[u][i-j][0]+f[kkz][j-2][0]);
}
}
}
int main()
{
while(scanf("%d%d",&n,&k)!=EOF)
{
memset(f,0,sizeof(f));
for(int i=1;i<=n;i++)
{
scanf("%d",&akz);fi[i]=0;
for(int j=0;j<=k;j++) f[i][j][0]=f[i][j][1]=akz;
}
cnt=0;
for(int i=1;i