Loading [MathJax]/extensions/tex2jax.js

P2577:「ZJOI2005」午餐题解

主要思路

容易想出状态\(dp[i][j][k]\)代表前\(i\)个人在一号队列排\(j\)分钟及在二号队排\(k\)分钟的最小时间。然后发现\(k\)这一维可以直接消去,因为有\(k=sum[i]-j\)。所以把线性依赖消去后,方程就非常小清新了:

\[dp[i][j] = min\{dp[i][j], max\{dp[i – 1][j – persons[i].a], j + persons[i].b\}\},当persons[i].a\leq j\]

\[dp[i][j] = min\{dp[i][j], max\{dp[i – 1][j], sum[i] – j + persons[i].b\}\}\]

代码

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// P2577.cpp
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define ll long long
using namespace std;
const int MX_N = 220;
struct person
{
ll a, b;
bool operator<(const person &ps) const
{
return b > ps.b;
}
} persons[MX_N];
ll sum[MX_N], n, dp[MX_N][MX_N * MX_N];
int main()
{
scanf("%lld", &n);
for (int i = 1; i <= n; i++)
scanf("%lld%lld", &persons[i].a, &persons[i].b);
sort(persons + 1, persons + 1 + n);
for (int i = 1; i <= n; i++)
sum[i] = sum[i - 1] + persons[i].a;
memset(dp, 0x3f, sizeof(dp));
dp[0][0] = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= sum[i]; j++)
{
if (j >= persons[i].a)
dp[i][j] = min(dp[i][j], max(dp[i - 1][j - persons[i].a], (ll)(j + persons[i].b)));
dp[i][j] = min(dp[i][j], max(dp[i - 1][j], sum[i] - j + persons[i].b));
}
ll ans = 0x7fffffff;
for (int i = 0; i <= sum[n]; i++)
ans = min(ans, dp[n][i]);
printf("%lld", ans);
return 0;
}
// P2577.cpp #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #define ll long long using namespace std; const int MX_N = 220; struct person { ll a, b; bool operator<(const person &ps) const { return b > ps.b; } } persons[MX_N]; ll sum[MX_N], n, dp[MX_N][MX_N * MX_N]; int main() { scanf("%lld", &n); for (int i = 1; i <= n; i++) scanf("%lld%lld", &persons[i].a, &persons[i].b); sort(persons + 1, persons + 1 + n); for (int i = 1; i <= n; i++) sum[i] = sum[i - 1] + persons[i].a; memset(dp, 0x3f, sizeof(dp)); dp[0][0] = 0; for (int i = 1; i <= n; i++) for (int j = 1; j <= sum[i]; j++) { if (j >= persons[i].a) dp[i][j] = min(dp[i][j], max(dp[i - 1][j - persons[i].a], (ll)(j + persons[i].b))); dp[i][j] = min(dp[i][j], max(dp[i - 1][j], sum[i] - j + persons[i].b)); } ll ans = 0x7fffffff; for (int i = 0; i <= sum[n]; i++) ans = min(ans, dp[n][i]); printf("%lld", ans); return 0; }
// P2577.cpp
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define ll long long
using namespace std;
const int MX_N = 220;
struct person
{
    ll a, b;
    bool operator<(const person &ps) const
    {
        return b > ps.b;
    }
} persons[MX_N];
ll sum[MX_N], n, dp[MX_N][MX_N * MX_N];
int main()
{
    scanf("%lld", &n);
    for (int i = 1; i <= n; i++)
        scanf("%lld%lld", &persons[i].a, &persons[i].b);
    sort(persons + 1, persons + 1 + n);
    for (int i = 1; i <= n; i++)
        sum[i] = sum[i - 1] + persons[i].a;
    memset(dp, 0x3f, sizeof(dp));
    dp[0][0] = 0;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= sum[i]; j++)
        {
            if (j >= persons[i].a)
                dp[i][j] = min(dp[i][j], max(dp[i - 1][j - persons[i].a], (ll)(j + persons[i].b)));
            dp[i][j] = min(dp[i][j], max(dp[i - 1][j], sum[i] - j + persons[i].b));
        }
    ll ans = 0x7fffffff;
    for (int i = 0; i <= sum[n]; i++)
        ans = min(ans, dp[n][i]);
    printf("%lld", ans);
    return 0;
}

Leave a Reply

Your email address will not be published. Required fields are marked *