状态转移

今天搞了一道大水题,却屡次wrong,不说了,见题目:

#include<bits/stdc++.h>
using namespace std;
const int maxn=25;
int f[maxn][maxn][maxn],n,t,m,w[maxn],ans;    
//f[i][j][k]表示第i个歌曲从第j个光盘的第k分钟开始时的最大数目; 
inline int read()
{
    int x=0,ff=1;
    char ch=getchar();
    while(!isdigit(ch))
    {
        if(ch=='-') ff=-1;
        ch=getchar();
    }
    while(isdigit(ch))
    {
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*ff;
}
inline void DP()
{
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            for(int k=0;k<=t;k++)
            {
                f[i][j][k]=f[i-1][j][k];
                if(k>=w[i]) f[i][j][k]=max(f[i-1][j][k],f[i-1][j][k-w[i]]+1);
                else  if(j>1&&t>=w[i]) f[i][j][k]=max(f[i-1][j][k],f[i-1][j-1][t-w[i]]+1);
            }
        }
    }
}
int main()
{
    freopen("1.in","r",stdin);
    n=read();t=read();m=read();    
    for(int i=1;i<=n;i++) w[i]=read();
    DP();
    cout<<f[n][m][t]<<endl;
    return 0;
}

和背包问题类似,个人刚开始打了很久...

DP有时还要利用贪心,比如这道题,歌如果放不下第j个磁盘,就放上一个的最后位置;

最后要说的就是状态转移必须切合实际,依照实情转移状态:本题中的else  if(j>1&&t>=w[i])就让我改了许久!

还有01背包如果不是模板题,最好还是不要省一维,还有要加上状态的复制...

原文地址:https://www.cnblogs.com/gcfer/p/10583727.html