完全背包问题,把休息日的划分变成每一段时间,分别对每一段时间进行完全背包dp,把每一个阶段的dp结果相加,最后得到的就是我们的分段完全背包的答案
#include<iostream> #include<algorithm> #include<cstring> using namespace std ; const int N = 2e5 + 10, M = 55 ; typedef long long LL ; LL n , m , q ; LL t[N] , a[N] ; LL f[N] ; LL c[N] , w[N] ; int main(){ cin >> n >> m >> q ; for(int i = 1 ; i <= q ; i ++) cin >> a[i] ; for(int i = 1 ; i <= q ; i ++){ t[i] = a[i] - a[i-1] - 1 ; } int tmp = n - a[q] ; q++ ; t[q] = tmp ; for(int i = 1 ; i <= m ; i ++){ int x , y ; cin >> x >> y ; int p = 1 ; for(int i = 0 ; i < x ; i ++) p*= 2 ; c[i] = p ; w[i] = y ; } LL ans = 0; for(int k = 1 ;k <= q ; k ++){ memset(f,0,sizeof(f)) ; for(int i = 1 ; i <= m ; i ++){ for(int j = c[i] ; j <= t[k] ; j ++){ f[j] = max(f[j] , f[j-c[i]] + w[i]) ; } } ans += f[t[k]] ; } cout << ans << endl ; }