选课 && 有线电视网
题目描述
在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数学总是在其它课程之前学习。现在有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 }