链接
https://www.luogu.com.cn/problem/P1174
思路
刚开始的思路:设置dp[i][j]:前i列使用了j颗子弹,那么递推dpi,j=max(dpi,j,dpi-1,k+maxj-k),然后统计在第i列使用了j-k颗子弹会多出来多少颗,把这些遍历加到前面,见代码。喜提70pts。但是搞不懂哪里错了。
看了评论区的dp:
70pts代码
#include<bits/stdc++.h>
using namespace std;#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define int long longusing namespace std;const int N = 1e3 + 10;
int n, m, k;
int mp[N][N];
int has[N][N];
int dp[N][N];
//dp[i][j]:前i列用了j发子弹,然后利用前缀和
void init()
{for (int j = 1; j <= m; j++)for (int i = n; i > 0; i--)mp[i][j] += mp[i + 1][j],has[i][j] += has[i + 1][j];
}signed main()
{IOS;cin >> n >> m >> k; for (int i = 1; i <= n; i++)for (int j = 1; j <= m; j++){cin >> mp[i][j];char x; cin >> x; has[i][j] = (x == 'Y')?1:0;}init();for (int j = 1; j <= k; j++){int now = min(j, n) ;int cal = min(has[n - now + 1][1] + now, n);dp[1][j] = mp[n - cal + 1][1];}for (int i = 2; i <= m; i++)for (int j = 1; j <= k; j++){for (int l = 0; l <= j; l++){int now = min(j - l, n);int add = has[n - now + 1][i];for (int ik = 0; ik <= add; ik++){int cal2= min(add - ik + now, n);dp[i][j] = max(dp[i][j], dp[i - 1][min(l + ik,k)] + mp[n - cal2 + 1][i]);}}}cout << dp[m][k];return 0;
}
AC代码
#include<bits/stdc++.h>
using namespace std;#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define int long longusing namespace std;int n, m, k;
bool c[205][205];
char x;
int a[205][205];
int dy[205][405], dn[205][405], dpn[205][405], dpy[205][405];
signed main() {IOS;cin >> n >> m >> k;for (int i = 1; i <= n; i++) {for (int j = 1; j <= m; j++) {cin >> a[i][j] >> x;if (x == 'Y') c[i][j] = 1;}}for (int j = 1; j <= m; j++) {int tot = 0;for (int i = n; i >= 1; i--) {if (c[i][j] == 1) dy[j][tot] += a[i][j];else {tot++;dn[j][tot] = dy[j][tot - 1] + a[i][j];dy[j][tot] = dn[j][tot];}}}for (int i = 1; i <= m; i++) {for (int j = 0; j <= k; j++) {for (int l = 0; l <= min(j, n); l++) {dpy[i][j] = max(dpy[i][j], dpy[i - 1][j - l] + dy[i][l]);if (l != 0) dpn[i][j] = max(dpn[i][j], dpy[i - 1][j - l] + dn[i][l]);if (j != l) dpn[i][j] = max(dpn[i][j], dpn[i - 1][j - l] + dy[i][l]);//如果不是所有的子弹都投到j列}}}cout<<dpn[m][k];return 0;
}