DP水题集合
book
归档:
OI
flag
[COGS 131][USACO Mar08] 奶牛渡河
题目地址:COGS
DP方程
令$dp(i)$为前$i$头牛渡河的最短时间,$m(i)$为一次带$i$头牛过河所花费的时间,则有方程: $$ dp(i)=\min_{2\leq 2j\leq i}{dp(j)+dp(i-j)+m(0),m(i)} $$
对方程的解释
$2\leq 2j\leq i$等价于$1\leq j\leq i-j$ ,即枚举与前面的牛分成一组过河所需时间,然后取最小值
代码
#include <bits/stdc++.h>
using namespace std;
int n;
const int maxn = 3000;
const int INF = 1 << 30;
int dp[maxn], m[maxn];
int main()
{
freopen("cowriver.in", "r", stdin);
freopen("cowriver.out", "w", stdout);
cin >> n >> m[0];
for (int i = 1; i <= n; ++i)
cin >> m[i], m[i] += m[i - 1];
for (int i = 1; i <= n; ++i)
dp[i] = INF;
for (int i = 1; i <= n; ++i)
{
dp[i] = m[i];
for (int j = 1; (j << 1) <= i; ++j)
dp[i] = min(dp[j] + dp[i - j] + m[0], dp[i]);
}
cout << dp[n] << endl;
}
[COGS 146][USACO Jan08] 贝茜的晨练计划
题目地址:COGS
DP方程
状态设计
注意到疲劳度和时间均对答案(距离)有影响,定义$f(i,j)$为前$i$分钟内疲劳度为$j$时所能行进的最远距离
方程
$$
\begin{cases}
f(i,0)=\max{ f(i-j,j)}&i-j \geq0&(1)\
f(i,j)=\max{f(i-1,j-1)+d(i)}&&(2)
\end{cases}
1\leq j\leq m
$$
解释
对于$(1)$式,就是从以前一直休息,休息到当前。对于$(2)$式,可以认为是从上一状态跑来的
代码
#include <bits/stdc++.h>
using namespace std;
int n, m;
const int maxn = 10010;
const int maxm = 510;
int f[maxn][maxm], d[maxn];
int main()
{
freopen("cowrun.in", "r", stdin);
freopen("cowrun.out", "w", stdout);
cin >> n >> m;
for (int i = 1; i <= n; ++i)
cin >> d[i];
for (int i = 1; i <= n; ++i)
{
f[i][0] = f[i - 1][0];
for (int j = 1; j <= m; ++j)
{
if (i - j >= 0)
f[i][0] = max(f[i][0], f[i - j][j]);
f[i][j] = max(f[i][j], f[i - 1][j - 1] + d[i]);
}
}
cout << f[n][0] << endl;
}
[COGS156][USACO Nov07] 挤奶时间
题目地址:COGS
DP方程
状态设计
令$f(i)$表示在第$i$个时间段内所能挤奶的最大值,用$range(i)$表示第$i$个区间。
DP方程
首先对所有区间排序,然后进行一波DP:
$$
\begin{array}
f(i)=\max{range(i).value+f(j)}&range(j).r+r\leq range(i).l
\end{array}
$$
这个应该很显然了吧。。
代码
#include <bits/stdc++.h>
using namespace std;
struct range
{
int l, r, v;
const bool operator<(const range &s) const
{
if (l != s.l)
return l < s.l;
else
return r < s.r;
}
};
int n, m, r;
const int maxm = 1010;
range ra[maxm];
int f[maxm];
int main()
{
freopen("milkprod.in", "r", stdin);
freopen("milkprod.out", "w", stdout);
cin >> n >> m >> r;
for (int i = 1; i <= m; ++i)
cin >> ra[i].l >> ra[i].r >> ra[i].v;
sort(ra + 1, ra + 1 + m);
for (int i = 1; i <= m; ++i)
f[i] = ra[i].v;
for (int i = 2; i <= m; ++i)
for (int j = 1; j <= i; ++j)
if (ra[j].r + r <= ra[i].l)
f[i] = max(f[i], ra[i].v + f[j]);
cout << *max_element(f + 1, f + 1 + m) << endl;
}
navigate_before
Blog再次迁移
Codeforces Round 22 B. The Golden Age
navigate_next