卧薪尝胆,厚积薄发。
USACO2007JAN GOLD Problem Solving
Date: Sun Oct 28 17:20:49 CST 2018
In Category:
NoCategory
Description:
请人来解决问题,必须按顺序解决,第一个月给
$a[i]$
元,第二个月给
$b[i]$
元,从第二个月开始每月获得
$m$
元,问最少几个月可以解决全部问题。
$1\leqslant n\leqslant 300$
Solution:
还是利用那个把要求解的答案放到状态里的方法,设
$f[i][j]$
表示到了解决了
$i$
个问题,花了
$j$
个月,第
$j+1$
个月已经用的钱最小值为
$f[i][j]$
,知道了状态之后问题就很好解决了,转移为
$f[i][k+1]=\min(sb[i]-sb[j](f[j][k]+sa[i]-sa[j]\leqslant m))$
,最后找一个
$f[n][i]$
不为零的最小的
$i$
即可。
Code:
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cctype>
#include<cstring>
using namespace std;
int m,n;
#define MAXN 310
int a[MAXN],b[MAXN];
int sa[MAXN],sb[MAXN];
int f[MAXN][MAXN << 1];
int main()
{
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,0x3f,sizeof(f));
f[0][0] = 0;
for(int i = 1;i <= n;++i)
{
for(int j = 0;j <= i;++j)
{
for(int k = 0;k <= 2 * n;++k)
{
if(f[j][k] + sa[i] - sa[j] <= m && sb[i] - sb[j] <= m)
{
f[i][k + 1] = min(f[i][k + 1],sb[i] - sb[j]);
}
}
}
}
for(int k = 1;k <= 2 * n;++k)
{
if(f[n][k] != 0x3f3f3f3f)
{
cout << k + 2 << endl;
break;
}
}
return 0;
}
In tag:
DP-DP
Copyright © 2020
wjh15101051
ღゝ◡╹)ノ♡