【♂Not The Triumph♂O(∩_∩)O哈哈~But The Struggle♂】

竞赛决不是捷径,它只是另一种艰辛的生活方式。得到与失去,只有时间会去评判;成功与失败,只有历史能去仲裁。我不会永远成功,正如我不会永远失败一样

  C++博客 :: 首页 :: 联系 ::  :: 管理
  6 Posts :: 239 Stories :: 25 Comments :: 0 Trackbacks

常用链接

留言簿(7)

我参与的团队

搜索

  •  

积分与排名

  • 积分 - 104698
  • 排名 - 233

最新评论

阅读排行榜

评论排行榜

Description
在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数学总是在其它课程之前学习。现在有N门功课,每门课有个学分,每门课有一门或没有直接先修课(若课程a是课程b的先修课即只有学完了课程a,才能学习课程b)。一个学生要从这些课程里选择M门课程学习,问他能获得的最大学分是多少?

Input
第一行有两个整数N,M用空格隔开。(1<=N<=200,1<=M<=150)
接下来的N行,第I+1行包含两个整数ki和si, ki表示第I门课的直接先修课,si表示第I门课的学分。若ki=0表示没有直接先修课(1<=ki<=N, 1<=si<=20)。

Output
只有一行,选M门课程的最大得分。

Sample Input
7 4
2 2
0 1
0 4
2 1
7 1
7 6
2 2

Sample Output
13

分析:
  由题意可知树形DP可以解决,每个课程可有选修和不选修两种到达,满足无后效性。
  F[i][j]表示以i为根(主修)选j个到达i的选修课程的最大得分。
  s[i]表示选i门课程的最大分数总和。
  状态方程:s[m]=max(F[root][k]+s[j]){0<=k<=m && 0<=j<=m && k+j<=m};

【参考程序】:

#include<cstring>
#include
<cstdio>
#include
<iostream>
using namespace std;

int F[500][500],a[500][500];
int num[500],s[500],w[500];
int n,m;
void tree_dp(int v)
{
    
for (int i=1;i<=num[v];i++) tree_dp(a[v][i]);
    memset(s,
0,sizeof(s));
    
for (int i=1;i<=num[v];i++)
        
for (int j=m;j>=0;j--)
            
for (int k=0;k<=m;k++)
                
if (j+k<=m)
                    
if (F[a[v][i]][k]+s[j]>s[j+k])
                        s[j
+k]=F[a[v][i]][k]+s[j];
    
if (v==0)
    {
        printf(
"%d\n",s[m]); exit(0);
    }
    
else
        
for (int i=1;i<=m;i++) F[v][i]=s[i-1]+w[v];
}
int main()
{
    
//freopen("choose.in","r",stdin);
    
//freopen("choose.out","w",stdout);
    scanf("%d%d",&n,&m);
    memset(num,
0,sizeof(num));
    
int wh;
    
for (int i=1;i<=n;i++)
    {
        scanf(
"%d%d",&wh,&w[i]);
        num[wh]
++;
        a[wh][num[wh]]
=i;
    }
    tree_dp(
0);
    
return 0;
}


 

posted on 2009-08-24 16:13 开拓者 阅读(190) 评论(0)  编辑 收藏 引用 所属分类: 树形DP

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理