洛谷P1280 尼克的任务
题目链接
解题思路
动态规划,这几天断断续续想了这个题,难点在于递推关系式的构造。
顺着更新的话,第
i
i
i个时刻需要知道第
i
+
1
i+1
i+1时刻的值,这显然是不太方便的,所以这里记
f
[
i
]
f[i]
f[i]为第
i
i
i个时刻到第
n
n
n个时刻的值,逆着更新。其中
b
[
i
]
b[i]
b[i]为以第
i
i
i个时刻为起点的所有时间段的统计。
f
[
i
]
=
f
[
i
+
1
]
+
1
b
[
i
]
=
0
f[i]=f[i+1]+1 \quad b[i]=0
f[i]=f[i+1]+1b[i]=0
f
[
i
]
=
m
a
x
(
f
[
i
]
,
f
[
i
+
a
[
c
n
t
]
.
t
]
)
b
[
i
]
≠
0
f[i]=max(f[i],f[i+a[cnt].t]) \quad b[i]\ne 0
f[i]=max(f[i],f[i+a[cnt].t])b[i]̸=0
由于为
a
[
i
]
.
p
a[i].p
a[i].p逆序排列,所以可以用
c
n
t
cnt
cnt来判断第
i
i
i个时刻为起点的持续时间。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int mx=10010;
//f[i]=f[i+1]+1
//f[i]=f[i+t]
struct node{
int p,t;
}a[mx];
bool cmp(node a,node b){
return a.p>b.p;//降序
}
int f[mx],b[mx],cnt=1;
int main(int argc, char** argv) {
int N,K;
scanf("%d%d",&N,&K);
for(int i=1;i<=K;i++) {
scanf("%d%d",&a[i].p,&a[i].t);
b[a[i].p]++;//储存相同时间起点
}
sort(a+1,a+K+1,cmp);
// for(int i=1;i<=K;i++){
// printf("%d %d\n",a[i].p,a[i].t);
// }
for(int i=N;i>=1;i--){//倒数第二个时间开始
if(!b[i]) f[i]=f[i+1]+1;
else{
for(int j=1;j<=b[i];j++){
f[i]=max(f[i],f[i+a[cnt].t]);
cnt++;
}
}
}
printf("%d\n",f[1]);
return 0;
}