
这是一个完全背包的题,可以利用完全背包来解决。
java
//package com.js.datastructure.recursion.蓝桥.国特训练营.动态规划线性DP;
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int[] kkk = new int[21];
kkk[0] = 1;
for (int i = 1; i < 21; i++) {
kkk[i] = kkk[i-1] * 2;
}
//1~n天中选择一些日子健身
//有m个健身计划,第i个健身计划,需要2^ki天,获得健身增益si
//有q天有其他安排
//
int n = scanner.nextInt();
int m = scanner.nextInt();
int q = scanner.nextInt();
int[] t = new int[q];
for (int i = 0; i < q; i++) {
t[i] = scanner.nextInt();
}
int[] k = new int[m];
int[] s = new int[m];
//记录值
for (int i = 0; i < m; i++) {
k[i] = kkk[scanner.nextInt()];
s[i] = scanner.nextInt();
}
//定义dp[i]为间隔天数为i时的最大收益数,转化为完全背包,正序遍历
long[] dp = new long[n+1];
for (int i = 0; i < m; i++) {
if(k[i] > n){
continue;
}
dp[k[i]] = Math.max(s[i],dp[k[i]]);
for (int j = 0; j < n+1; j++) {
if(dp[j] != 0 && j + k[i] < n+1){
dp[j + k[i]] = Math.max(dp[j] + s[i],dp[j + k[i]]);
}
}
}
//处理dp数组,满足题目中的
int now = 0;
for (int i = 0; i < n + 1; i++) {
if(dp[i] != 0){
now = i;
}else {
dp[i] = dp[now];
}
}
//把时间段摘出来,进行填充
ArrayList<Integer> time = new ArrayList<>();
time.add(t[0] - 1);
for (int i = 1; i < q; i++) {
time.add(t[i] - t[i-1] - 1);
}
time.add(n - t[q-1]);
long ans = 0;
for(int tt : time){
ans = ans + dp[tt];
}
System.out.println(ans);
}
}