P1174 打砖块

链接

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 long

using 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 long

using 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;
}
posted @   WHUStar  阅读(1)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示