计蒜客 30994

题目链接:https://nanti.jisuanke.com/t/30994

样例输入:

5
5 6 0
4 5 1 1
3 4 1 2
2 3 1 3
1 2 1 4

样例输出:

55

样例输入:

1
-100 0 0

样例输出:

0

题解:

把n道题目做了或者没做作为状态,裸的状压DP。

其中当前的时间 t,就是当前做了的题目数量加上1。

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll INF=1e18;

const int maxn=22;

int n;
struct P{
    ll a,b;
    int pre;
}p[maxn];

ll dp[1<<maxn];

int main()
{
    cin>>n;
    for(int i=1,s;i<=n;i++)
    {
        scanf("%lld%lld",&p[i].a,&p[i].b);

        scanf("%d",&s);
        p[i].pre=0;
        for(int j=1,o;j<=s;j++)
        {
            scanf("%d",&o);
            p[i].pre=p[i].pre|(1<<(o-1));
        }
    }
    //for(int i=1;i<=n;i++) printf("%lld %lld %d
",p[i].a,p[i].b,p[i].pre);

    for(int sta=0;sta<(1<<n);sta++) dp[sta]=-INF;
    dp[0]=0;

    ll ans=0;
    for(int sta=0;sta<(1<<n);sta++)
    {
        if(dp[sta]==-INF) continue;

        ll t=1;
        for(int i=1;i<=n;i++) if(sta&(1<<(i-1))) t++;

        for(int i=1;i<=n;i++)
        {
            if(sta&(1<<(i-1))) continue;

            if(p[i].pre==0 || (p[i].pre&sta)>=p[i].pre)
            {
                int nxt=sta|(1<<(i-1));
                dp[nxt]=max(dp[nxt],dp[sta]+t*p[i].a+p[i].b);
                ans=max(dp[nxt],ans);
            }
        }
    }

    cout<<ans<<endl;
}

时间复杂度 $Oleft( {2^n cdot n} ight)$,n = 20 时为2e7,1s足够。

原文地址:https://www.cnblogs.com/dilthey/p/9570205.html