题意:
有n张CD(n<=20),每张能播放的时长不同。给定一个时长限制t,挑出部分的CD使得总播放时间最长。顺便输出路径!
思路:
重点在输出路径,否则这题很普通。那就要用二维数组记录每个CD是否要携带了,开个二维bool记录即可,位置就跟dp数组一样的,然后根据带或不带,来决定上一件物品在那个格子中。带了就在上一行的j-价值中,不带就在上一行的j中。
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 using namespace std; 5 const int N=30; 6 int track[N]; 7 int dp[N][100000]; 8 bool path[N][100000]; 9 10 void DFS(int n,int t) 11 { 12 if(t==0) 13 return; 14 if(path[t][n]==true) 15 { 16 DFS( n-track[t-1], t-1); 17 printf("%d ",track[t-1]); 18 } 19 else 20 DFS(n, t-1); 21 } 22 23 int cal(int n, int t) 24 { 25 for(int i=0; i<t; i++) 26 { 27 for(int j=0; j<track[i]; j++)//必要的,不然全是0 28 dp[i+1][j] = dp[i][j]; 29 30 for(int j=track[i]; j<=n; j++) 31 { 32 if( dp[i][j-track[i]]+track[i] >= dp[i][j] ) 33 { 34 dp[i+1][j] = dp[i][j-track[i]]+track[i]; 35 path[i+1][j]=true; 36 } 37 else dp[i+1][j] = dp[i][j]; 38 } 39 } 40 DFS( n, t);//递归输出路径 41 printf("sum:%d ", dp[t][n]); 42 return 0; 43 } 44 int main() 45 { 46 //freopen("input.txt","r",stdin); 47 int n, t; 48 while(cin>>n>>t) 49 { 50 memset(track,0,sizeof(track)); 51 memset(dp,0,sizeof(dp)); 52 memset(path, 0, sizeof(path)); 53 54 int cnt=0; 55 for(int i=0; i<t; i++) 56 { 57 scanf("%d",&track[i]); 58 cnt+=track[i]; 59 } 60 if(cnt<=n)//全部都能带的情况 61 { 62 for(int i=0; i<t; i++) 63 printf("%d ", track[i]); 64 printf("sum:%d ",cnt); 65 } 66 else cal(n, t); 67 } 68 return 0; 69 }