程序设计思维与实践 Week16 CSP模拟

在这里插入图片描述


思路:定义一个stirng接受数字,遍历string,用一个size为10的数组来记录出现过的数字。


#include <iostream>
#include <string>
using namespace std;

int ans;
bool number[10];
int getNumber(string s)
{
	int len = s.length(), cnt = 0;
	for (int i = 0; i < len; i++)
	{
		if (!number[s[i] - '0']) cnt++;
		number[s[i] - '0'] = true;
	}
	return cnt;
}
int main()
{
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
	int n, k; cin >> n >> k;
	while (n--)
	{
		memset(number, 0, sizeof(number));
		string s; cin >> s;
		ans += getNumber(s) < k;
	}
	cout << ans;
}

反思:一开始用了set,超时了,set会增加log的复杂度(更好笑的是我想了好久不用stl怎么做


在这里插入图片描述
思路:用二维数组a记录下每两点之间的距离。这道题是要找出距离最远的点最近的点,那只要遍历每个点并更新ans即可。


#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <iomanip>
using namespace std;
const int MAXN = 1e3 + 5;
long long a[MAXN][MAXN];

long long getDistance(pair<int, int> p1, pair<int, int> p2)
{
	return pow(p1.first - p2.first, 2) + pow(p1.second - p2.second, 2);
}
int main()
{
	int N; cin >> N;
	pair<int, int> ansPoint(1000009, 1000009);
	long long maxTrue = 1e15;
	vector<pair<int, int>> v;
	for (int i = 0; i < N; i++)
	{
		int x, y; cin >> x >> y;
		v.push_back(make_pair(x, y));
	}
	for (int i = 0; i < N - 1; i++)
		for (int j = i + 1; j < N; j++)
			a[i][j] = a[j][i] = getDistance(v[i], v[j]);
	for (int i = 0; i < N; i++)
	{
		a[i][i] = 0;
		double theMax = *max_element(a[i], a[i] + N);
		if ((theMax < maxTrue) || (theMax == maxTrue && v[i] < ansPoint))
		{
			maxTrue = theMax;
			ansPoint = v[i];
		}
	}
	cout << fixed << vectorprecision(2) << (double)ansPoint.first << ' '
		<< (double)ansPoint.second << endl
		<< (double)maxTrue;
}

在这里插入图片描述


思路:一个dp题,一颗树的解决方案可以甩锅给两个子树,剩下的问题就是判断根和两个子节点是否满足最大共有大于1的条件。为了省时间,先算出两个数之间的最大公约数是否>1,存在bool数组g中。我用的递归dp,所以把算出来的结果存在数组中。
具体来说,递归函数bool solve(int b, int r, int e),含义是解决左段为l,根为r,右端为e的情况是否能构成一颗树,先递归判断左,即solve(b,k,r-1),其中k为[b,r-1]的任意值,再用同样方法判断右,如果可行,返回true。


#include <iostream>
#include <vector>
#pragma comment(linker, "/STACK:102400000,102400000")

using namespace std;
const int MAXN = 700 + 5;
int a[MAXN];
bool g[MAXN][MAXN];
bool record1[MAXN][MAXN];
bool record2[MAXN][MAXN];
bool b1[MAXN][MAXN];
bool b2[MAXN][MAXN];
int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); }

bool solve(int b, int r, int e)
{
	if (!b1[b][r])
	{
		b1[b][r] = true;
		if (b == r) record1[b][r] = true;
		for (int i = b; i < r; i++)
			if (solve(b, i, r - 1) && g[r][i])
			{
				record1[b][r] = true;
				break;
			}
	}
	if (!record1[b][r]) return false;
	if (!b2[r][e])
	{
		b2[r][e] = true;
		if (r == e) record2[r][e] = true;
		for (int i = r + 1; i <= e; i++)
			if (solve(r + 1, i, e) && g[r][i])
			{
				record2[r][e] = true;
				break;
			}
	}
	return record2[r][e];
}
int main()
{
	int t; cin >> t;
	while (t--)
	{
		memset(record1, 0, sizeof(record1));
		memset(record2, 0, sizeof(record2));
		memset(b1, 0, sizeof(b1));
		memset(b2, 0, sizeof(b2));
		int n; cin >> n;
		for (int i = 0; i < n; i++) cin >> a[i];
		for (int i = 0; i < n - 1; i++)
			for (int j = i; j < n; j++)
				g[i][j] = g[j][i] = gcd(a[i], a[j]) > 1;
		bool flag = false;
		for (int i = 0; i < n; i++)
			if (solve(0, i, n - 1))
			{
				flag = true;
				break;
			}
		if (flag) cout << "Yes";
		else cout << "No";
		if (t) cout << '\n';
	}
}

反思:写右子树情况的时候,复制的左子树,有一处忘了改了,找了好半天的错。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值