动态规划专项intermediate:LA 4015

来源:互联网 发布:淘宝的管理团队 编辑:程序博客网 时间:2024/05/16 07:40

被自己蠢哭了……已经想到是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;}


原创粉丝点击