RQNOJ 140 分配时间:dp
题目链接:https://www.rqnoj.cn/problem/140
题意:
小王参加的考试是几门科目的试卷放在一起考,一共给t分钟来做。
他现在已经知道第i门科目花k分钟可以拿到w[i][k]分。
写名字需要的时间为name(他写自己的名字很慢)
如果放弃某一门的考试(花的时间为0),那么名字也就不用写了。
问他最高能得几分。
题解:
表示状态:
dp[i][j] = max score
i:考虑到第i们科目
j:当前花费的时间
找出答案:
max dp[n][j]
如何转移:
now: dp[i][j]
dp[i+1][j+k] = max dp[i][j] + w[i][k] + (k==0 ? 0 : name)
枚举k为当前科目用的时间。k为0时相当于放弃本科目,也就不用写名字。
边界条件:
dp[0][0] = 0
others = -1
AC Code:
1 // state expression: 2 // dp[i][j] = max score 3 // i: considering ith subject 4 // j: cost time 5 // 6 // find the answer: 7 // max dp[n][j] 8 // 9 // transferring: 10 // now: dp[i][j] 11 // dp[i+1][j+k] = max dp[i][j] + w[i][k] + (k==0 ? 0 : name) 12 // 13 // boundary: 14 // dp[0][0] = 0 15 // others = -1 16 #include <iostream> 17 #include <stdio.h> 18 #include <string.h> 19 #define MAX_N 15 20 #define MAX_T 105 21 22 using namespace std; 23 24 int n,t; 25 int name; 26 int ans; 27 int w[MAX_N][MAX_T]; 28 int dp[MAX_N][MAX_T]; 29 30 void read() 31 { 32 cin>>t>>n>>name; 33 for(int i=0;i<n;i++) 34 { 35 w[i][0]=0; 36 for(int j=1;j<=t;j++) 37 { 38 cin>>w[i][j]; 39 } 40 } 41 } 42 43 void solve() 44 { 45 memset(dp,-1,sizeof(dp)); 46 dp[0][0]=0; 47 for(int i=0;i<n;i++) 48 { 49 for(int j=0;j<=t;j++) 50 { 51 if(dp[i][j]!=-1) 52 { 53 for(int k=0;k<=t;k++) 54 { 55 int tim=j+k+(k==0?0:name); 56 if(tim<=t) dp[i+1][tim]=max(dp[i+1][tim],dp[i][j]+w[i][k]); 57 else break; 58 } 59 } 60 } 61 } 62 ans=0; 63 for(int i=0;i<=t;i++) 64 { 65 ans=max(ans,dp[n][i]); 66 } 67 } 68 69 void print() 70 { 71 cout<<ans<<endl; 72 } 73 74 int main() 75 { 76 read(); 77 solve(); 78 print(); 79 }