洛谷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;
}

 

posted @ 2019-01-04 13:44  墨白——oier  阅读(198)  评论(0编辑  收藏  举报