luoguP1174 打砖块

solution

本来直接写的背包,结果是错误的。
因为最后一枪0->-1->0是不行的。
所以从前到后一次背包,从后到前一次背包。
然后枚举在哪里打的最后一枪。
除了最后一枪都没有什么顺序关系

code

#include <bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<=b;++i)
#define int long long
using namespace std;
const int _=307;
// const int mod=1e9+7;
int read() {
    int x=0,f=1;char s=getchar();
    for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
    for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
    return x*f;
}
int a[_][_],b[_][_];
int g[_][_],f[_][_],sum_a[_][_],sum_b[_][_];
void solve() {
    int n=read(),m=read(),shoot=read(),ans=0;
    for(int i=n;i>=1;--i) FOR(j,1,m) {
        int x;char s;
        cin>>x>>s;
        a[i][j]=x;
        b[i][j]=(s=='N');
    }
    FOR(i,1,n) FOR(j,1,m) {
        sum_a[i][j]=sum_a[i-1][j]+a[i][j];
        sum_b[i][j]=sum_b[i-1][j]+b[i][j];
    }
    memset(f,-0x3f,sizeof(f));
    memset(g,-0x3f,sizeof(g));
    f[0][shoot]=g[m+1][shoot]=0;
    FOR(i,1,m) FOR(j,0,n) FOR(k,1,shoot) {
        if(k+sum_b[j][i]>shoot) continue;
        f[i][k]=max(f[i][k],f[i-1][k+sum_b[j][i]]+sum_a[j][i]);
        ans=max(ans,f[i][k]);
    }
    for(int i=m;i>=1;--i) FOR(j,0,n) FOR(k,1,shoot) {
        if(k+sum_b[j][i]>shoot) continue;
        g[i][k]=max(g[i][k],g[i+1][k+sum_b[j][i]]+sum_a[j][i]);
        ans=max(ans,g[i][k]);
    }
    FOR(i,1,m) FOR(j,0,n) FOR(k,1,shoot) {
        if(b[j][i]&&k-sum_b[j][i]>=0&&shoot-(k-sum_b[j][i])>0) {
            ans=max(ans,sum_a[j][i]+f[i-1][k]+g[i+1][shoot-(k-sum_b[j][i])]);
        }
    }
    cout<<ans<<"\n";
}
signed main() {
    #ifdef ONLINE_JUDGE
    #else
        freopen("a.in","r",stdin);
        // freopen("a.out","w",stdout);
    #endif
    int T=read();
    while(T--) {
        solve();
    }   
    return 0;
}
posted @   小饼卷大葱  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示