题解 P2113 【看球泡妹子】

· · 题解

题目

看来各位的转移方程都是三维的,我这里有二维的

首先三维的楼上都说的挺清楚的,我就不再赘述

我们其实可以,类比01背包压缩空间(很明显,一场比赛不会为你打两次)

我们设f[x][y]为进行了y次,使女的满意值为x的男的最大满意值

类比01背包,我们可以认为这是个二维01背包,因此,容易得出:

f[x][y]=max(f[x][y],f[x-v[i]][y-1]+w[i])

其中,v[i],w[i]分别为女男的满意度(可以通过v[i]=b[p[i]]+b[q[i]] , w[i]=a[p[i]]*a[q[i]]得到)

由于十分明显,女的一开始对男的满意度为0,所以我们只能从0开始推

即把f的值都附为 -inf ,然后使f[0][y]=0即可

所以dp如下:

    memset(f,143,sizeof(f));
    memset(f[0],0,sizeof(f[0]));    
    for(int i=1;i<=m;i++)
        for(int j=s;j>=v[i];j--)
            for(int x=1;x<=k;x++)
                f[j][x]=max(f[j][x],f[j-v[i]][x-1]+w[i]);   
    for(int i=c;i<=s;i++) ans=max(ans,f[i][k]);

同时,有一个新问题:s是多少?

其他题解一般是开m的20倍,那大概是因为再大就mle了,所以其实他们的解法其实上有一定问题,只不过数据比较水,只要把k,c加到20多,他们题解就gg了,所以按最严格的的来说:

我们必须压到二维,而s为前k个最大的vi

所以AC代码如下:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
int n,m,k,c,s,a[111],b[111],p[111],q[111];
ll v[111],w[111],v1[111],f[100001][101],ans=-1e9;//f[x][y]:进行y次,使女的满意值为x 
int main()
{
    memset(f,143,sizeof(f));
    memset(f[0],0,sizeof(f[0]));
    cin>>n>>m>>k>>c;
    for(int i=1;i<=n;i++)   scanf("%lld",a+i);
    for(int i=1;i<=n;i++)   scanf("%lld",b+i);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&p[i],&q[i]);
        w[i]=a[p[i]]*a[q[i]];
        v1[i]=v[i]=b[p[i]]+b[q[i]];
    }
    sort(v1+1,v1+1+m);
    for(int i=m;i>=m-k+1;i--)   s+=v1[i];
    for(int i=1;i<=m;i++)
        for(int j=s;j>=v[i];j--)
            for(int x=1;x<=k;x++)
                f[j][x]=max(f[j][x],f[j-v[i]][x-1]+w[i]);   
    for(int i=c;i<=s;i++) ans=max(ans,f[i][k]);
    if(ans<0) puts("-1");
    else cout<<ans;
    return 0;
}