CSP-M4补题

A - TT数鸭子

B - ZJM要抵御宇宙射线

C - 宇宙狗的危机

A - TT数鸭子

题目

在这里插入图片描述

思路

用stl会超时。。。最后用的vis标记统计数字种类数。

代码

#include <iostream>
#include <cstring>
using namespace std;
int n,k,ans=0,cnt,size_,temp;
string s;
bool vis[11]; 
int main() {
	ios::sync_with_stdio(false);
	cin>>n>>k; 
	for(int i=1;i<=n;i++) {
		memset(vis,0,sizeof vis);
		cin>>s;
		cnt=0;
		size_=s.size();
		for(int j=0;j<size_;j++) {
			temp=s[j]-'0';
			if(vis[temp]==0) {
				vis[temp]=1;
				cnt++;
			}
		}
		if(cnt<k) ans++;
	}
	cout<<ans<<endl;
	return 0;
} 

B- ZJM要抵御宇宙射线

题目

在这里插入图片描述

思路

看成最小圆覆盖,没看到题中说圆心是坐标点之一。。。遍历每两个点之间的距离,取所有距离中最大的距离,即为最大半径的最小值。

代码

#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;

int n; 
double R;
struct point{
	double x,y,r;
	int maxp;
	bool operator<(const point p_) {
		if(x==p_.x) return y<p_.y;
		else return x<p_.x;
	}
}p[1100],ans;

double dis(point a,point b) {
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}


int main() {
	cin>>n;
	for(int i=1;i<=n;i++) cin>>p[i].x>>p[i].y;
	sort(p+1,p+n+1);
	for(int i=1;i<=n;i++) {
		double tempr,maxr_=0;
		int temp;
		for(int j=1;j<=n;j++) {
			tempr=dis(p[i],p[j]);
			if(tempr>maxr_) {
				maxr_=tempr;
				temp=j;
			}
		}
		p[i].r=maxr_;
		p[i].maxp=temp;
	}
	int ans=1;
	for(int i=1;i<=n-1;i++) {
		if(p[ans].r>p[i].r) {
			ans=i;
		}
	}
	printf("%.2lf %.2lf\n",p[ans].x,p[ans].y);
	printf("%.2lf\n",p[ans].r*p[ans].r);
	return 0;
}

C- 宇宙狗的危机

题目

在这里插入图片描述

思路

采用动态规划的区间DP思想。用ans[i][j]表示a[i]-a[j]可以构成二叉树,则ans[1][n]为答案。用m[i][j]表示以a[i]为根的子树可以和以a[j]为根的子树合并,用Left[i][j]表示可以以a[j]为根,a[i]-a[j-1]作为左子树,用Right[i][j]表示可以以a[i]为根,a[i+1][j]作为右子树。经过区间长度,起始位置,根节点的枚举,最终得出答案。

代码

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int t,n,a[750];
bool ans[750][750],m[750][750],Left[750][750],Right[750][750];

int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); }

int main(){
	cin >> t;
	for(int iii = 1; iii <= t; iii++){
		memset(ans, 0, sizeof ans);
		memset(m, 0, sizeof m);
		memset(Left, 0, sizeof Left);
		memset(Right, 0, sizeof Right);
		cin >> n;
		for (int i = 1; i <= n; i++) {
			cin >> a[i];
			Left[i][i] = 1;
			Right[i][i] = 1;
			ans[i][i] = 1;
		}
		for (int i = 1; i <= n; i++){
			for (int j = 1; j <= n; j++){
				if (gcd(a[i], a[j]) > 1){
					m[i][j] = 1;	
				}
			}
		}
		for (int len = 0; len < n; len++){
			for (int start = 1; start <= n-len; start++){
				int end = start + len;
				for (int root = start; root <= end; root++)
					if (Left[start][root] && Right[root][end]){
						ans[start][end] = 1;
						if (m[root][end + 1]) Left[start][end + 1] = 1;
						if (m[start - 1][root]) Right[start - 1][end] = 1;
					}
			}
		}
		if (ans[1][n]) cout << "Yes" << endl;
		else cout << "No" << endl;
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值