题解 P2113 【看球泡妹子】

· · 题解

(题目名称与背景成功吸引了我)

每两个队伍的比赛可以看做一个重量b[p[i]]+b[q[i]],价值a[p[i]]*a[q[i]]的物品

转化为最多选k次的01背包

dp[i][t][j]表示 已经选i个,本次选到了第t个,小红满意度j时 小明的最大满意度

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=110;
int p[N],q[N],a[N],b[N],dp[N][N][20*N];
int main(){
    int n,m,i,j,t,k,c,ans=0;
    scanf("%d%d%d%d",&n,&m,&k,&c);
    for(i=1;i<=n;i++)scanf("%d",&a[i]);
    for(i=1;i<=n;i++)scanf("%d",&b[i]);
    for(i=1;i<=m;i++)scanf("%d%d",&p[i],&q[i]);
    memset(dp,0,sizeof(dp));
    for(i=1;i<=k;i++)
       for(t=i;t<=m;t++)
           for(j=20*m;j>=0;j--){//Ai<=10,上界2*10*m
               dp[i][t][j]=max(dp[i][t][j],dp[i][t-1][j]);
               if(j>=b[p[t]]+b[q[t]])
                   if(dp[i-1][t-1][j-b[p[t]]-b[q[t]]]>0||j==b[p[t]]+b[q[t]])
                   //dp[i-1][t-1][j-b[p[t]]-b[q[t]]]的状态可以到达 或者 第一次选
                  //第一次选的状态也可以在dp前预处理
                       dp[i][t][j]=max(dp[i][t][j],
                       dp[i-1][t-1][j-b[p[t]]-b[q[t]]]+a[p[t]]*a[q[t]]);
               if(j>=c)ans=max(ans,dp[i][t][j]);}
    if(ans>0)cout<<ans<<endl;
        else cout<<-1<<endl;
return 0;}