ICPC南東ヨーロッパコンテスト2019 B.レベルアップ(DP)


トピックへのリンクトピックの主な考え方:
合計2つのレベルがあり、n個のタスクがあり、各タスクは第1レベルで取得した経験値と所要時間を持ち、各タスクは第2レベルで取得した経験も持っています必要な価値と時間。第1レベルのアップグレード後の追加の経験は、第2レベルに入れられます。Q. 2つのレベルに進むのに必要な最小時間はどれくらいですか?そうでない場合は、-1を出力します。

問題解決のアイデア:
dp [i] [j]を定義して、第1レベルのエクスペリエンスがiになり、第2レベルのエクスペリエンスがjになるのに必要な最小時間を取得します。01ナップザックを使用して逆順で解決し、最初のいくつかのタスクのこの次元を減らすことを検討してください。
重要:エクスペリエンスの最初のレベルは昇順でソートする必要があります。そうしないと、dpの結果に影響します。経験の最初のレベルが90、40、40で、必要な最初のレベルの経験が100の場合、オーバーフローの状況は130だけですが、40、40、90には40 + 90 = 130、40 +があります。 40 + 90 = 170の2つのケースなので、昇順で並べ替えます。それ以外の場合は省略されます。

問題解決コード:

#include<bits/stdc++.h>
using namespace std;
mt19937 rng_32(chrono::steady_clock::now().time_since_epoch().count());
typedef long long ll;
const ll maxn=2e5+10;
ll inf=1e18;
ll dp[1010][1010];
struct E{
    int x,t,y,r;
}p[505];
bool cmp(E a1,E a2)
{
    return a1.x<a2.x;
}
int main()
{
    ll n,s1,s2;
    cin>>n>>s1>>s2;
    for (ll i=0;i<=1000;i++)
    {
        for (ll j=0;j<=1000;j++)
        dp[i][j]=inf;
    }
    dp[0][0]=0;
    for (ll i=1;i<=n;i++)
    {
        cin>>p[i].x>>p[i].t>>p[i].y>>p[i].r;
    }
    sort(p+1,p+1+n,cmp);
    for (ll i=1;i<=n;i++)
    {
        for (ll j=1000;j>=0;j--)
        {
            for (ll k=1000;k>=0;k--)
            {
                ll t1=inf,t2=inf;
                if (j>=p[i].x && j-p[i].x<s1)
                t1=dp[j-p[i].x][k]+p[i].t;

                if (k>=p[i].y)
                t2=dp[j][k-p[i].y]+p[i].r;
             
                dp[j][k]=min(dp[j][k],min(t1,t2));
            }
        }
    }
    ll ans=inf;
    for (ll j=s1;j<=1000;j++)
    {
        for (ll k=max(0ll,s2-(j-s1));k<=1000;k++)
        {
            ans=min(ans,dp[j][k]);
        }
    }
    if (ans==inf)
    ans=-1;
    cout<<ans;
    return 0;
}
12個のオリジナル記事を公開 いいね1 訪問数327

おすすめ

転載: blog.csdn.net/qq_41818939/article/details/105527105