5359: [Lydsy1805月赛]寻宝游戏 DP

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/baidu_36797646/article/details/82841286

题解:

选择 k k 个位置交换实际上是一条路径上,有 k k 个属于这条路径上的权值不计贡献,有 k k 个不属于路径的权值计入贡献。所以直接DP, f [ i ] [ j ] [ p ] [ q ] f[i][j][p][q] 表示到了 ( i , j ) (i,j) ,路径上有 p p 个权值不计贡献,在前 i 1 i-1 行和第 i i 行的前 j j 个没选的权值中有 q q 个权值计入贡献即可。

代码:

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pa pair<int,int>
const int Maxn=55;
const int Maxk=25;
const int inf=2147483647;
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    return x*f;
}
int n,m,k,a[Maxn][Maxn],f[Maxn][Maxn][Maxk][Maxk];
int d[Maxn],s[Maxn];
void upd(int &x,int y){x=max(x,y);}
bool cmp(int x,int y){return x>y;}
int main()
{
    int T=read();
    while(T--)
    {
        memset(f,-1,sizeof(f));
        n=read(),m=read(),k=read();
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        a[i][j]=read();
        f[1][1][0][0]=a[1][1];
        f[1][1][1][0]=0;
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            int c=0;
            for(int l=j+1;l<=m;l++)d[++c]=a[i][l];
            for(int l=1;l<j;l++)d[++c]=a[i+1][l];
            sort(d+1,d+1+c,cmp);
            s[0]=0;
            for(int l=1;l<=c;l++)s[l]=s[l-1]+d[l];
            for(int p=0;p<=k;p++)
            for(int q=0;q<=k;q++)
            if(f[i][j][p][q]!=-1)
            {
                int t=f[i][j][p][q];
                if(j<m)
                {
                    upd(f[i][j+1][p][q],t+a[i][j+1]);
                    if(p<k)upd(f[i][j+1][p+1][q],t);
                }
                if(i<n)
                {
                    upd(f[i+1][j][p][q],t+a[i+1][j]);
                    if(p<k)upd(f[i+1][j][p+1][q],t);
                    for(int l=1;q+l<=k&&l<=c;l++)
                    {
                        upd(f[i+1][j][p][q+l],t+a[i+1][j]+s[l]);
                        if(p<k)upd(f[i+1][j][p+1][q+l],t+s[l]);
                    }
                }
            }
        }
        int ans=0;
        for(int i=0;i<=k;i++)upd(ans,f[n][m][i][i]);
        printf("%d\n",ans);
    }
}

猜你喜欢

转载自blog.csdn.net/baidu_36797646/article/details/82841286
今日推荐