dp+差分数组

前言:怎么也没想到要用dp来做,并且这个题目中如果列为1的话还要特殊考虑


题目地址

在这里插入图片描述
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;

//#define int long long
const int N = (int)5e3 + 10;
int dp[N][N][2]; // 0 表示上端点,1表示下端点
int t;
int n, m;
int a[N];
int chafen[N];
signed main() {
	cin >> t;
	while (t--) {
		cin >> n >> m;
		for (int i = 0; i <= n; i++) {
			for (int j = 0; j <= m; j++) {
				dp[i][j][0] = dp[i][j][1] = 0;
				a[i] = 0;
			}
		}
		for (int i = 1; i <= m; i++) {
			cin >> a[i];
		}
		for (int i = 1; i <= n; i++) {
			dp[i][1][0] = dp[i][1][1] = 1; // 第一列中都可以当端点
		}
		for (int j = 2; j <= m - 1; j++) {
			if (a[j] == 1) {
				//vector<int> chafen(n + 2, 0);
				for (int i = 0; i < n + 2; ++i)
					chafen[i] = 0;
				for (int k = 1; k <= n; k++) {
					if (dp[k][j - 1][0]) chafen[k]++;
					if (dp[k][j - 1][1]) chafen[k + 1]--;
				}
				int cnt = 0;
				for (int k = 1; k <= n; k++) {
					cnt += chafen[k];
					if (cnt) {
						dp[k][j][0] = dp[k][j][1] = 1;
					}
				}
				continue;
			}
			for (int i = 1; i <= n; i++) {

				if (dp[i][j - 1][0]) {
					if (i - a[j] + 1 >= 1) {
						dp[i][j][1] = 1;
						dp[i - a[j] + 1][j][0] = 1;
					}
				}
				if (dp[i][j - 1][1]) {
					if (i + a[j] - 1 <= n) {
						dp[i][j][0] = 1;
						dp[i + a[j] - 1][j][1] = 1;
					}
				}
			}
		}
		//for (int i = 1; i <= n; i++) {
		//	cout << dp[i][2][0] << " " << dp[i][2][1] << endl;
		//}
		//vector<int> chafen(n + 2, 0);
		for (int i = 0; i < n + 2; ++i)
			chafen[i] = 0;
		for (int i = 1; i <= n; i++) {
			if (dp[i][m - 1][0]) chafen[i]++;
			if (dp[i][m - 1][1]) chafen[i + 1]--;
		}int cnt = 0; int ans = 0;
		for (int i = 1; i <= n; i++) {
			cnt += chafen[i];
			if (cnt) ans++;
		}
		cout << ans << endl;
	}
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wniuniu_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值