2021csp 赛前第三次集训 - 动规专题

2008 普及组T3 传球游戏
#include <bits/stdc++.h>
using namespace std;

const int N = 40;
int n, m, dp[N][N];

int main() {
	cin >> n >> m;

	//第0次传球在0号同学手中的方法数是1,即初始状态
	dp[0][0] = 1;
	
	//状态转移依赖于上一次传球的状态,所以外循环是1...m
	for (int i = 1; i <= m; i ++) {
		for (int j = 0; j < n; j ++) {
			//dp[i][j]表示第i次传球在j号同学手中的方法数
			dp[i][j] = dp[i-1][(j+1)%n] + dp[i-1][(j-1+n)%n];
		}
	}
	cout << dp[m][0] << endl;

	return 0;
}
2007 普及组T3 守望者的逃离
  • 时间复杂度:O(T*M),超时
#include <bits/stdc++.h>
using namespace std;

const int M = 1e3 + 100;
int m, s, t, maxx;
int a[M], b[M];

int main() {
	cin >> m >> s >> t;
	
	//b[j]表示上一秒剩余j点魔法值,能走的最远距离
	//a[j]表示现在剩余j点魔法值,能走的最远距离
    for (int i = 1; i <= t; i ++) {
    	maxx = 0;
    	for (int j = 0; j <= m; j ++) {
    		a[j] = b[j] + 17;      								//不使用魔法
			if (j + 10 <= m) a[j] = max(a[j], b[j+10] + 60);    //使用魔法
			if (j >= 4) a[j] = max(a[j], b[j-4]);               //原地休息

    		maxx = max(maxx, a[j]);
		}
		memcpy(b, a, sizeof(a));    //a数组复制到b数组
		
		if (maxx >= s) {
			cout << "Yes" << endl << i << endl;
			return 0;
		}
	}
	
	cout << "No" << endl << maxx << endl;

	return 0;
}
  • 时间复杂度:O(T)
#include <bits/stdc++.h>
using namespace std;

const int M = 3e5 + 10;
int m, s, t, maxx;
int a[M], b[M];

int main() {
	cin >> m >> s >> t;

	//a和b两个人选择不同的策略,a[i]和b[i]分别表示他们在第i秒钟走的距离
    for (int i = 1; i <= t; i ++) {
    	//a:优先使用魔法,如果魔法值不够,就休息恢复
    	if (m >= 10) a[i] = a[i-1] + 60, m -= 10;
		else a[i] = a[i-1], m += 4;

		//b:优先跑步,但如果a更快的话,就抄作业;
		b[i] = b[i-1] + 17;
		if (a[i] > b[i]) b[i] = a[i];
		
		//显然,b跑的不会比a慢
		if (b[i] >= s) {
			cout << "Yes" << endl << i << endl;
			return 0;
		}
	}

	cout << "No" << endl << b[t] << endl;

	return 0;
}
2003普及组T2 数字游戏
#include <bits/stdc++.h>
using namespace std;

const int N = 105, M = 10, INF = 0x3f3f3f3f;
int n, m;
int a[N], s[N];
int mi[N][N][M], ma[N][N][M], minn, maxx;

int main() {
	cin >> n >> m;
	for (int i = 1; i <= n; i ++) cin >> a[i], a[i+n] = a[i];
	for (int i = 1; i <= 2*n; i ++) s[i] = s[i-1] + a[i];

	maxx = 0, minn = INF;
	memset(mi, 0x3f, sizeof(mi));

	for (int len = 1; len <= n; len ++) {       		//枚举长度,状态转移依赖于更短的len
		for (int l = 1; l + len - 1 <= 2*n; l ++) {		//枚举起点
			int r = l + len - 1;                        //终点由起点和长度决定
			mi[l][r][1] = ma[l][r][1] = ((s[r] - s[l-1]) % 10 + 10) % 10;
			for (int i = 2; i <= m; i ++) {     		//枚举分块数
				//j - l + 1 = i - 1
				for (int j = l + i - 2; j < r; j ++) {  //把a[l...j]分成i-1块,a[j+1...r]为一块
					int t = ((s[r]-s[j]) % 10 + 10) % 10;
					mi[l][r][i] = min(mi[l][r][i], mi[l][j][i-1] * t);
					ma[l][r][i] = max(ma[l][r][i], ma[l][j][i-1] * t);
				}
			}
		}
	}

	for (int i = 1; i <= n; i ++) {
		minn = min(minn, mi[i][i+n-1][m]);
		maxx = max(maxx, ma[i][i+n-1][m]);
	}

	cout << minn << endl;
	cout << maxx << endl;

	return 0;
}
2020普及组T4 方格取数
#include <bits/stdc++.h>
#define LL long long
using namespace std;

const int N = 1e3 + 10;
int n, m, a[N][N];
LL dp[N][N][2];
//dp[i][j][0]表示从左边或上面走过来的路径的最大值
//dp[i][j][1]表示从左边或下面走过来的路径的最大值

LL myMax(LL a, LL b, LL c) {
	return max(a, max(b, c));
}

int main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i ++) for (int j = 1; j <= m; j ++) cin >> a[i][j];

	memset(dp, 0xcf, sizeof(dp));
	dp[1][0][0] = 0;

	for (int j = 1; j <= m; j ++) {
		for (int i = 1; i <= n; i ++) {
			dp[i][j][0] = myMax(dp[i-1][j][0], dp[i][j-1][0], dp[i][j-1][1]) + a[i][j];
		}
		
		
		for (int i = n; i >= 1; i --) {
			dp[i][j][1] = myMax(dp[i+1][j][1], dp[i][j-1][0], dp[i][j-1][1]) + a[i][j];
		}
	}

	cout << dp[n][m][0] << endl;

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值