洛谷1437 敲砖块

洛谷1437 敲砖块


原题链接


交题记录

N/A 考试题。。。


题解

先来观察一下性质。

1 1 12 23 

由这个和样例很容易想到这样存储:

1 1 1
2 2
3

即“左对齐”存储。
状态就是\(f[k][i][j]\),表示只在(i,j)和(i,j)上方打最大的收入。
然而并不好转移
的确不好转移。。。。。
呵呵呵
可以无视上面
但如果这样存呢

1
1 2
1 2 3

可以理解为“斜过来”,即:

.//
//
/

再把斜线组成的行看做新行。
现在下面变成了左边。
所以设\(f[i][j][k]\),在第\(i\)行取前\(j\)个,且一共取了\(k\)个的最大收入
\(f[i][j][k]=max{f[i-1][l][k-j]+s[i][j]}(l=j-1..i-1)\)
即枚举选几个。
注意特判l


Code

// It is made by XZZ
#include
#include
#include
using namespace std;
#define rep(a,b,c) for(rg int a=b;a<=c;a++)
#define drep(a,b,c) for(rg int a=b;a>=c;a--)
#define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
#define il inline
#define rg register
#define vd void
typedef long long ll;
il int gi(){rg int x=0,f=1;rg char ch=getchar();while(ch<'0'||ch>'9')f=ch=='-'?-1:f,ch=getchar();while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;
}
int n,m,v[51][51],s[51][51],ss[51],ans=0;
int f[51][51][501];
int main(){
//     #define Fname "brike"// freopen(Fname".in","r",stdin);// freopen(Fname".out","w",stdout);n=gi(),m=gi();rep(j,1,n)drep(i,n,j)v[i][j]=gi();rep(i,1,n)rep(j,1,i)s[i][j]=v[i][j]+s[i][j-1];memset(f,-1,sizeof f);f[0][0][0]=0;rep(i,1,n)rep(j,0,i){rep(k,j,m)rep(l,max(0,j-1),i-1)if(f[i-1][l][k-j]+1)f[i][j][k]=max(f[i][j][k],f[i-1][l][k-j]+s[i][j]);ans=max(ans,f[i][j][m]);}printf("%d\n",ans);return 0;
}

【代码wa了一个点,有人看出来请指正】

转载于:https://www.cnblogs.com/xzz_233/p/7442169.html


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部