标签:style blog class code ext int
对于分组背包,每组选且只选一件商品的写法只想出了二维数组的写法。
dp[s][k] 表示 在前s类中选取价格为 k 的商品的最优解。
dp[s][k] = max( dp[s-1][k-product[s][j].c] + product[s][j].w)。dp[s][k]每次只会有dp[s-1]更新得到,保证了前s-1类商品的选取。
对于此题,可以把每棵子树的情况看成一类商品,递归求解。
dp[s][k]表示在s子树上投入k个机器人时的最优解。
当k == 0时,表示在s点投入1个机器人,且此机器人又返回s点,当k >= 1时,表示在s点投入k个机器人且都不返回的s结点时的最优解。
更新时显而易见的有,每棵子树选取一种情况下最优解来更新根节点的最优解。写法即为上面的二位分组背包,但是此题貌似范围较大建议滚动数组。
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#pragma comment(linker, "/STACK:1024000000");
#define EPS (1e-8)
#define LL long long
#define ULL unsigned long long LL
#define _LL __int64
#define _INF 0x3f3f3f3f
#define Mod 1000000007
#define LM(a,b) (((ULL)(a))<<(b))
#define RM(a,b) (((ULL)(a))>>(b))
using namespace std;
const LL MAXN = 10010;
struct N
{
int u,v,w,next;
} edge[MAXN*2];
int head[MAXN];
int Top;
void Link(int u,int v,int w = -1)
{
edge[Top].u = u;
edge[Top].v = v;
edge[Top].w = w;
edge[Top].next = head[u];
head[u] = Top++;
}
void Init_head_Top(int n)
{
memset(head,-1,sizeof(int)*(n+2));
Top = 0;
}
int dp[12][MAXN];
int dfs(int s,int pre,int k)
{
if(dp[k][s] != -1)
return dp[k][s];
int val[2][14];
memset(val,-1,sizeof(val));
int site = 1;
bool mark = false;
for(int p = head[s]; p != -1; p = edge[p].next)
{
if(edge[p].v != pre)
{
if(mark == false)
{
mark = true;
memset(val[site&1],-1,sizeof(val[site&1]));
for(int j = 0; j <= k; ++j)
{
int t = dp[j][edge[p].v] == -1 ? dfs(edge[p].v,s,j) : dp[j][edge[p].v];
if(j == 0)
val[site&1][j] = t + edge[p].w*2;
else
val[site&1][j] = t + edge[p].w*j;
}
}
else
{
memset(val[site&1],-1,sizeof(val[site&1]));
for(int i = 0; i <= k; ++i)
{
if(val[(site-1)&1][i] != -1)
{
for(int j = k; j >= 0; --j)
{
if(i+j <= k)
{
int temp;
int t = dp[j][edge[p].v] == -1 ? dfs(edge[p].v,s,j) : dp[j][edge[p].v];
if(j == 0)
temp = t + edge[p].w*2 + val[(site-1)&1][i];
else
temp = t + edge[p].w*j + val[(site-1)&1][i];
if(val[site&1][i+j] == -1 || val[site&1][i+j] > temp)
val[site&1][i+j] = temp;
}
}
}
}
}
site++;
}
}
for(int i = 0;i <= k; ++i)
{
if(val[(site-1)&1][i] != -1)
dp[i][s] = val[(site-1)&1][i];
else dp[i][s] = 0;
}
// cout<<"k = "<<k<<" s = "<<s<<" dp = "<<dp[k][s]<<endl;
return dp[k][s];
}
int main()
{
int n,s,k;
int u,v,w;
while(scanf("%d %d %d",&n,&s,&k) != EOF)
{
Init_head_Top(n);
for(int i = 0; i <= k; ++i)
{
memset(dp[i],-1,sizeof(int)*(n+2));
}
for(int i = 1; i < n; ++i)
{
scanf("%d %d %d",&u,&v,&w);
Link(u,v,w);
Link(v,u,w);
}
dfs(s,-1,k);
int Min = dp[1][s];
for(int i = 1; i <= k; ++i)
{
Min = min(Min,dp[i][s]);
// cout<<"dp = "<<dp[i][s]<<endl;;
}
printf("%d\n",Min);
}
return 0;
}
HDU 4003 Find Metal Minaral 树上瞎搞分组背包,布布扣,bubuko.com
HDU 4003 Find Metal Minaral 树上瞎搞分组背包
标签:style blog class code ext int
原文地址:http://blog.csdn.net/zmx354/article/details/24937405