今天搞了一道大水题,却屡次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背包如果不是模板题,最好还是不要省一维,还有要加上状态的复制...