您的位置:首页 > 其它

动态规划专项intermediate:LA 4015

2013-05-09 22:03 260 查看
被自己蠢哭了……已经想到是dfs里分组背包,可就是不知道怎么写,看题解才知道怎么做,然后细节和边界条件又想了半天才弄明白。

其实就是用dp[i][V][0]表示以i为根结点遍历V个点并回到i所需的最小能量,dp[i][V][1]表示以i为根节点遍历V个点(不需回到i)所需的最小能量。

然后就是分组背包了,然后还得注意边界条件,因为V个点作为物品必须全部取完,所以边界为dp[root][1][0]=dp[root][1][1]=0,否则赋为inf。

具体的状态方程就看代码吧。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int inf=1<<30;
int n,e,q,s;
int head[510],pnt[510],nxt[510],cost[510],in[510];
void addedge(int u,int v,int c)
{
pnt[e]=v;cost[e]=c;nxt[e]=head[u];head[u]=e++;
}
int dp[510][510][2];
int cnt[510];
void dfs(int u)
{
dp[u][1][0]=dp[u][1][1]=0;
cnt[u]=1;
for(int i=head[u];i!=-1;i=nxt[i])
{
int v=pnt[i];
dfs(v);
cnt[u]+=cnt[v];
for(int V=cnt[u];V>1;V--)
{
for(int j=1;j<=V&&j<=cnt[v];j++)
{
dp[u][V][0]=min(dp[u][V][0],dp[u][V-j][0]+dp[v][j][0]+cost[i]*2);
dp[u][V][1]=min(dp[u][V][1],dp[u][V-j][0]+dp[v][j][1]+cost[i]*1);
dp[u][V][1]=min(dp[u][V][1],dp[u][V-j][1]+dp[v][j][0]+cost[i]*2);
}
}
}
}
int main()
{
freopen("in.txt","r",stdin);
int kase=1;
while(cin>>n&&n)
{
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
dp[i][j][0]=dp[i][j][1]=inf;
memset(head,-1,sizeof(head));
memset(in,0,sizeof(in));
e=0;
for(int i=0;i<n-1;i++)
{
int u,v,c;
cin>>u>>v>>c;
addedge(v,u,c);
in[u]++;
}
for(int i=0;i<n;i++) if(!in[i]) s=i;
dfs(s);
cout<<"Case "<<kase++<<":"<<endl;
cin>>q;
while(q--)
{
int x;
cin>>x;
int ans;
for(int i=1;i<=n;i++)
{
if(x>=dp[s][i][0]||x>=dp[s][i][1])
ans=i;
else break;
}
cout<<ans<<endl;
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: