洛谷P2876 [USACO07JAN]解决问题Problem Solving
n <= 300 求最优问题 考虑动态规划 ;
f[i][j] 是 第i个月 完成了前j个任务
我们的决策有两个 (1) 不做任务 , 光还债;(2) 做任务
然后我们写出dp方程 (图中sa是预付款的前缀和 , sb是后付款的前缀和)
#include<cstdio> #include<queue> #include<map> #include<cstring> #include<cstdlib> #include<deque> #include<iostream> #include<vector> #include<algorithm> #define inf 0x3f3f3f3f #define M 309 #define ll long long using namespace std; int n , a[M] , b[M] , ans , m , sa[M] , sb[M] , f[M << 1][M]; int main(){ // freopen("A.out" , "w" , stdout); // freopen("c1.in" , "r" , stdin); scanf("%d%d" , &m , &n); for (int i = 1 ; i <= n ; ++i){ scanf("%d%d" , &a[i] , &b[i]); sa[i] = sa[i-1] + a[i] , sb[i] = sb[i-1] + b[i]; } memset(f , 0xcf , sizeof(f)); f[0][0] = m; for (int i = 1 ; i <= n * 2 + 10 ; ++i){ for (int j = 0 ; j <= n ; ++j){ if (f[i-1][j] >= 0) f[i][j] = m; } for (int j = 1 ; j <= n ; ++j){ for (int k = 0 ; k < j ; ++k){ if (f[i-1][k] >= sa[j] - sa[k] && sb[j] - sb[k] <= m){ f[i][j] = max (f[i][j] , m - sb[j] + sb[k]); } } } } for (int i = 1 ; i <= n * 2 + 5 ; ++i){ if (f[i][n] >= 0){ ans = i + 1 ; break; } } printf ("%d" , ans + 1); return 0; }