#include<bits/stdc++.h>
using namespace std;
const int N=220;
int dp[N][N][2],v[N][N][2],n,m,K;
int a[N][N],b[N][N];
signed main(){
cin>>n>>m>>K;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
char c;
int x;
cin>>x>>c;
a[i][j]=x;
if(c=='Y')b[i][j]=1;
}
}
for(int j=1;j<=m;j++){
int cnt=0;
for(int i=n;i>=1;i--){
if(b[i][j])v[j][cnt][1]+=a[i][j];
else cnt++,v[j][cnt][1]=v[j][cnt-1][1]+a[i][j],v[j][cnt][0]=v[j][cnt][1];
}
}
for(int i=1;i<=m;i++){
for(int j=0;j<=K;j++){
for(int k=0;k<=min(j,K);k++){
dp[i][j][1]=max(dp[i][j][1],dp[i-1][j-k][1]+v[i][k][1]);
if(k)dp[i][j][0]=max(dp[i][j][0],dp[i-1][j-k][1]+v[i][k][0]);
if(j-k)dp[i][j][0]=max(dp[i][j][0],dp[i-1][j-k][0]+v[i][k][1]);
}
}
}
cout<<dp[m][K][0];
}
这么好的题目怎么才蓝题…
这个Y砖块先选后给跟免费是差别很大的
很容易想到把每一列都当成一个物品
于是这道题就变成了分组背包问题
v[i][j][1]表示第i列花了j颗子弹最后一枪还在,这个时候遇到Y可以当成免费的直接累加分值
dp[i][j][1]表示前i列花了j颗子弹最后一枪还在
dp[i][j][0]表示前i列花了j颗子弹最后一枪不在
转移的时候注意边界情况的判断,合法才转移