[蓝桥杯][2014年第五届真题]地宫取宝

摘花生+LIS(要取得当前格子的物品,这个物品必须比当前所拥有的物品都大,所以物品的重量严格递增)的结合题。

状态表示:\(f(i,j,k,c)\):当前到达\((i,j)\)位置,已经取了\(k\)件物品,且最后一件物品的重量为\(c\)

状态转移:\((i,j)\)可以从\((i-1,j)\)抵达,也可以从\((i,j-1)\)抵达,抵达\((i,j)\)后可考虑选或不选当前位置上的物品,选的话则需满足上一件物品的重量严格小于当前物品的重量。

\[f(i,j,k,c)+=f(i,j-1,k,c); \\ f(i,j,k,c)+=f(i-1,j,k,c); \\ f(i,j,k,c)+=\sum_{0 \le w < c} f(i,j-1,k-1,w); \\ f(i,j,k,c)+=\sum_{0 \le w < c} f(i-1,j,k-1,w); \]

边界:

\[f(1,1,0,0)=1; \\ f(1,1,1,g[1][1])=1; \]

注意点

  1. 由于体积的范围为\(0 \le C_i \le 12\),我们将体积做加一处理,则体积的范围变成\(1 \le C_i \le 13\),这样第四维下标为\(0\)时可表示当前已选物品的最大体积为\(0\),即没有选任何物品,为边界状态。
  2. 如果不用体积来记录上一件选择的物品而使用下标来记录的话,则需要五维来表示状态,显然用体积更优。
const int N=55;
int g[N][N];
int f[N][N][15][15];
int n,m,k,c;

int main()
{
    cin>>n>>m>>k;

    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            cin>>g[i][j],g[i][j]++,c=max(c,g[i][j]);

    f[1][1][0][0]=1;
    f[1][1][1][g[1][1]]=1;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            for(int u=0;u<=k;u++)
                for(int v=0;v<=c;v++)
                {
                    int &fval=f[i][j][u][v];
                    fval=(fval+f[i-1][j][u][v])%mod;
                    fval=(fval+f[i][j-1][u][v])%mod;
                    if(u && v == g[i][j])
                    {
                        for(int w=0;w<g[i][j];w++)
                        {
                            fval=(fval+f[i-1][j][u-1][w])%mod;
                            fval=(fval+f[i][j-1][u-1][w])%mod;
                        }
                    }
                    
                }
            
     
    int res=0;           
    for(int i=1;i<=c;i++) res=(res+f[n][m][k][i])%mod;
    cout<<res<<endl;
     
    //system("pause");
    return 0;
}
posted @ 2021-03-22 12:43  Dazzling!  阅读(32)  评论(0编辑  收藏  举报