OJ 1430. Holiday scheduling
题目描述
你有 n 天的假期,每一天你有三种选择:
- 发呆。你不需要花钱,但也没有任何收入。
- 花费 x 元出去玩一天。
- 打工。有 m 项任务可以选择,第 i 项需要占用你第 s i s_i si 到 t i t_i ti 天的时间,完成一个任务可以获得 a i a_i ai元。你不能在某一天同时打两份工。
你最开始有 0 元。由于打工和发呆很无聊,你想在玩的天数尽可能多的情况下,赚尽量多的钱。
请输出你在假期结束后,最终会剩下多少钱。
Input
请从 stdin 读入。
输入第一行为三个正整数,n, m, x (
1
≤
n
≤
365
,
1
≤
m
≤
1
0
5
,
1
≤
x
≤
1
0
9
1≤n≤365,1≤m≤10^5,1≤x≤10^9
1≤n≤365,1≤m≤105,1≤x≤109)。
接下来 m 行,第 i 行有三个正整数
s
i
,
t
i
,
a
i
s_i, t_i, a_i
si,ti,ai
(
1
≤
s
i
≤
t
i
≤
n
,
1
≤
a
i
≤
1
0
9
)
(1≤ s_i≤t_i≤n,1≤a_i≤10^9)
(1≤si≤ti≤n,1≤ai≤109)。
Output
请输出到 stdout 中。
输出一行一个整数,表示你在假期结束后,最终会剩下多少钱。
Sample Input
Case1 人生得意须尽欢,莫使金樽空对月!
3 3 1
1 1 2
1 2 1000000000
2 3 1000000000
Case2 金樽空对月。
3 3 1
1 3 1000000000
2 3 1000000000
3 3 1000000000
Case3 尽管你第二天有钱玩,但是你不是三和大神,你是聪明的带学生。因此你会把第二天的工打了,再爽玩三天。
5 2 100
1 1 100
2 2 400
Sample Output
Case1
0
Case2
1000000000
Case3
200
Constraints
Time Limit: 1s
Memory Limit: 128MB
Solution
二维动态规划问题。根据打工和花钱列状态转移方程即可。注意数据范围,采用long long int(64位长整型)。
Code
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
vector<vector<long long>> g;//g[i][j] 从第i天到第j天打工赚的钱
vector<vector<long long>> dp;//dp[i][j]为剩余的钱 i:玩的天数 j:day
int main()
{
int n, m;
long long x;
cin>>n>>m>>x;
g.assign(n+1,vector<long long>(n+1,0));
dp.assign(n+1,vector<long long>(n+1,-1));
int s, t;
long long a;
for(int i=0;i<m;i++){
cin>>s>>t>>a;
g[s][t]=max(g[s][t],a);
}
for(int i=0;i<n+1;i++){
dp[0][i]=g[1][i];
}
for(int i=0;i<n+1;i++){
for(int j=i+1;j<n+1;j++){
if(dp[i][j]<0){
continue;
}
if(dp[i][j]>=x && j<n){
dp[i+1][j+1]=max(dp[i+1][j+1],dp[i][j]-x);
}
for(int k=j+1;k<n+1;k++){
dp[i][k]=max(dp[i][k],dp[i][j]+g[j+1][k]);
}
}
}
for(int i=n-1;i>=0;i--){
if(dp[i][n]>=0){
cout<<dp[i][n];
break;
}
}
return 0;
}