题意:吉哥的假期是1到n天,然后有m个工作可以让吉哥选择做,每个工作都有一个开始 t_s 和结束的时间 t_e ,都用天来表示,然后每个工作必须从第一天做到最后一天,
从头到尾做完之后就可以得到C的报酬,现在要求吉哥这个假期最多能赚到多少钱?
解题报告:这个题就是一个典型的一维的动态规划,规划的公式是dp[i] = max(dp[i-(job[j].t_e-job[j].t_s+1)]+job[j].c,dp[i]);然后这题还有一个可以优化的地方,就是可
以将所有的工作先按照结束的时间从小到大排个序,这样的话,如果判断到循环到的那个工作的结束的时间比当前正在更新的时间晚的话,就可以退出这一层的循环,注意只是退
出一层循环,下面贴出优化前和优化后的两种不同代码以便于对比:
优化前代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 7 struct node 8 { 9 int t_s,t_e,c; 10 }job[1005]; 11 int dp[105]; 12 int main() 13 { 14 int T; 15 scanf("%d",&T); 16 while(T--) 17 { 18 int n,m; 19 scanf("%d%d",&n,&m); 20 for(int i = 0;i < m;++i) 21 scanf("%d%d%d",&job[i].t_s,&job[i].t_e,&job[i].c); 22 memset(dp,0,sizeof(dp)); 23 int M = 0; 24 for(int i = 1;i <= n;++i) 25 for(int j = 0;j < m;++j) 26 if(job[j].t_e == i) 27 { 28 dp[i] = max(dp[i-(job[j].t_e-job[j].t_s+1)]+job[j].c,dp[i]); 29 M = max(M,dp[i]); 30 } 31 else dp[i] = max(dp[i],M); 32 printf("%d ",dp[n]); 33 } 34 return 0; 35 }
优化代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 7 struct node 8 { 9 int t_s,t_e,c; 10 friend bool operator < (node a,node b) 11 { 12 return a.t_e < b.t_e; 13 } 14 }job[1005]; 15 int dp[105]; 16 int main() 17 { 18 int T; 19 scanf("%d",&T); 20 while(T--) 21 { 22 int n,m; 23 scanf("%d%d",&n,&m); 24 for(int i = 0;i < m;++i) 25 scanf("%d%d%d",&job[i].t_s,&job[i].t_e,&job[i].c); 26 sort(job,job+m); //优化前的准备工作 27 memset(dp,0,sizeof(dp)); 28 int M = 0; 29 for(int i = 1;i <= n;++i) 30 for(int j = 0;j < m;++j) 31 { 32 if(job[j].t_e > i) //一个优化,当这个工作的时间比当前正在更新的时间晚的话,就可以退出这层的循环 33 break; 34 if(job[j].t_e == i) 35 { 36 dp[i] = max(dp[i-(job[j].t_e-job[j].t_s+1)]+job[j].c,dp[i]); 37 M = max(M,dp[i]); 38 } 39 else dp[i] = max(dp[i],M); 40 } 41 printf("%d ",dp[n]); 42 } 43 return 0; 44 }