zoukankan      html  css  js  c++  java
  • 选课 && 有线电视网

    题目描述

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

    输入输出格式

    输入格式:

    第一行有两个整数N,M用空格隔开。(1<=N<=300,1<=M<=300)

    接下来的N行,第I+1行包含两个整数ki和si, ki表示第I门课的直接先修课,si表示第I门课的学分。若ki=0表示没有直接先修课(1<=ki<=N, 1<=si<=20)。

    输出格式:

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

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<vector> 
     4 #include<cstring>
     5 using namespace std;
     6 const int maxn=1007;
     7 int score[maxn],f[maxn][maxn];
     8 int n,m;
     9 vector<int>son[maxn];
    10 void search(int x){
    11     f[x][0]=0;f[x][1]=score[x];
    12     for(int i=0;i<son[x].size();i++){
    13         int y=son[x][i];
    14         search(y);
    15         for(int u=m;u>=2;u--) 
    16             for(int v=u-1;v>=0;v--)
    17                 if(u>=v) f[x][u]=max(f[x][u],f[x][u-v]+f[y][v]);
    18         if(x==0){
    19         for(int j=m;j>=0;j--)
    20             f[x][j]=max(f[x][j],f[x][0]+f[y][j]); 
    21         } 
    22     }
    23 }
    24 int main(){
    25     cin>>n>>m;
    26     for(int i=1;i<=n;i++){
    27         int fa;cin>>fa>>score[i];
    28         son[fa].push_back(i);
    29     }
    30     memset(f,-1,sizeof(f));
    31     search(0);
    32     cout<<f[0][m]<<endl; 
    33     return 0;
    34 }

     

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<queue>
     7 #include<set>
     8 #include<map>
     9 #include<stack>
    10 #include<vector>
    11 using namespace std;
    12 const int maxn=3007;
    13 const int INF=0x7f7f7f7f;
    14 int n,m,num;
    15 int val[maxn],head[maxn],f[maxn][maxn],sz[maxn];
    16 struct Edge{
    17   int nxt,to,dis;
    18 }edge[maxn];
    19 void add(int from,int to,int dis){
    20   edge[++num].nxt=head[from];
    21   edge[num].to=to;
    22   edge[num].dis=dis;
    23   head[from]=num;
    24 }
    25 /*void dfs(int x){
    26   f[x][0]=0;
    27   if(x>n-m) {f[x][1]=val[x];return;}
    28   for(int i=head[x];i;i=edge[i].nxt){
    29     int v=edge[i].to;dfs(v);
    30     //for(int j=0;j<=sz[x];j++)
    31     //  for(int k=0;k<=sz[v];k++)
    32     //    {f[x][j]=max(f[x][j],f[v][k]+f[x][j-k]-edge[i].dis);cout<<x<<" "<<j<<" "<<f[x][j]<<endl;} 
    33     for(int j=sz[x];j>=0;j--){
    34       for(int k=0;k<=j;k++){
    35         f[x][j]=max(f[x][j],f[v][k]+f[x][j-k]-edge[i].dis);
    36         //cout<<x<<" "<<j<<" "<<f[x][j]<<endl; 
    37       }
    38     }
    39   } 
    40 } */
    41 int dfs(int x){
    42   f[x][0]=0;
    43   if(x>n-m){f[x][1]=val[x];return 1;}
    44   int tot=0;
    45   for(int i=head[x];i;i=edge[i].nxt){
    46     int v=edge[i].to;
    47     tot+=dfs(v);
    48     for(int j=tot;j>=0;j--)//防止一棵子树重复选 
    49       for(int k=0;k<=j;k++)
    50         f[x][j]=max(f[x][j],f[v][k]+f[x][j-k]-edge[i].dis);
    51   }
    52   return tot;
    53 }
    54 int main(){
    55   cin>>n>>m;memset(f,-INF,sizeof(f)); 
    56   for(int i=1;i<=n-m;i++){
    57     cin>>sz[i];
    58     for(int j=1;j<=sz[i];j++){
    59       int a,c;cin>>a>>c;
    60       add(i,a,c);
    61     }
    62   }
    63   for(int i=n-m+1;i<=n;i++) cin>>val[i];
    64   dfs(1);
    65   for(int i=m;i>=0;i--){
    66     if(f[1][i]>=0){cout<<i<<endl;return 0;}
    67   }
    68 }
  • 相关阅读:
    Linux-netstat
    API接口防止参数篡改和重放攻击
    Java中遍历Map的几种方式
    Java泛型中的标记符含义
    Iterator 和 for...of 循环
    Promise 对象
    Reflect
    正则要求密码长度最少12位,包含至少1个特殊字符,2个数字,2个大写字母和一些小写字母。
    一个JS正则表达式,一个正实数,整数部分最多11位 小数部分最多 8位
    java阿里云短信发送配置
  • 原文地址:https://www.cnblogs.com/lcan/p/9842338.html
Copyright © 2011-2022 走看看