第四次CSP 测试

TT数鸭子

题目

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

分析

这个看数据的范围很大,因此采用数组字符的形式进行存储,思路就是遍历数组,计算出现的数字的个数,需要注意的是复杂度的问题,降低复杂度的方法可以是将string  类型改为数组类型,同时数组取长度是strlen(a),而string 取长度是a.size(),或者a.length().

代码

#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
long long  num[11];
int main()
{
	int n,k;
	scanf("%d %d",&n,&k);
	char a[20];
	int ans=0;
	while(n--){
		//cin>>a;
		scanf("%s",a);
	//	cout<<a<<endl; 
		int t=0;
		for(int i=0;i<strlen(a);i++){
			num[a[i]-'0']++; 
			if(num[a[i]-'0']==1){
				t++;   
			} 
		}
		if(t<k)	ans++; 
		memset(num,0,sizeof(num));
	}
	printf("%d\n",ans);
	return 0;
 } 
 

ZJM 要抵制宇宙射线

题目

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

分析

提交的时候错误的地方:
(1)半径的平方算成半径
(2)数据类型,用float 过不去,需要用double
(3)属于优化部分,需要求的是点到其他各个点中距离最大值的最小值,我之前在求最小值的时候将数据存了起来,但是后来觉得没必要直接在第二层循环外更新最小值即可。

代码

#include<stdio.h>
#include<algorithm>
#include<cmath>
#include<iostream>
using namespace std;
#define maxn 1010
struct point{
	double x,y;
	bool operator < (const point& e)const{
		if(x!=e.x) return x<e.x;
		else if(y!=e.y)	return y<e.y;
		else return false;
	}
}a[maxn]; 
int main()
{
	int n;
	scanf("%d",&n);
	for(int i=0;i<n;i++){
		scanf("%lf %lf",&a[i].x,&a[i].y);
	}
	sort(a,a+n);  
	int i;
	int s=-1;
	double minn=1e15;
	for(i=0;i<n;i++){  //i 到其他点的距离 
		double tmp=0;
		for(int j=0;j<n;j++){
			double dis=(a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y);
			if(tmp<dis){  //取大的 
				tmp=dis;
			}
		}
		if(tmp<minn){
			minn=tmp;
			s=i;
		}
	} 
	printf("%.2lf %.2lf\n",a[s].x,a[s].y);
	printf("%.2lf\n",minn);
	
 } 

宇宙狗的危机

题目

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

分析

这道题在测试的时候一心想的是,找公因数有相同的直接连然后计算不同公因数直接的桥梁,然后连接,中间还涉及到缩点之类的想法,然后直接被想法劝退,然后只做了这个思路的第一步,只要任意点都有它的同伴就可以,当然这样思路漏洞是很明显的,没想到这样还能过5个点,美滋滋.直到下来看别人的思路才是一种恍然大悟的感觉,本身二叉搜索树就存在左子树右子树这样的子结构。然后联系gcd 就是连接条件,这样就用动态规划,区间dp.
其中L[i][j]指,以j 为根,区间[i,j-1]为j 的左儿子
R[i][j]指以i 为根,区间[i+1,j]作为i的右儿子。
设k为区间[l,r]的根,
如果L[l][k]=1且r[k][r]=1,则该状态合法,可以转移;
同时l1且rn则说明存在一颗以K为根的平衡二叉树。
如果k与l-1 存在大于1的公因数,那么可以拓展一位以l-1为根,[l,r]为右儿子
如果k与r+1存在大于1的公因数,同样拓展一位以r+1为根,[l,r]为左儿子
初始化的时候是两层循环遍历判断f[i][j]的状态,L和R 在输入的时候初始化,只有根。

代码

#include<stdio.h>
#include<string.h>
using namespace std;
#define maxn 710
int L[maxn][maxn],R[maxn][maxn],f[maxn][maxn],a[maxn];
int gcd(int a,int b){return b == 0 ? a : gcd(b,a%b);}
int main()
{
	int t,n;
	scanf("%d",&t);
	while(t--){
		memset(L,0,sizeof(L));
		memset(R,0,sizeof(R));
		memset(f,0,sizeof(f));
		scanf("%d",&n);
		for(int i=1;i<=n;i++){
			scanf("%d",&a[i]); 
			L[i][i]=1,R[i][i]=1;
		}  //输入数据完毕 
		//区间dp
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				if(gcd(a[i],a[j])>1){
					f[i][j]=f[j][i]=1;
				}
			}
		}
		bool flag=false;
		for(int l=n;l>=1;l--)
		{   //左边 
			for(int r=1;r<=n;r++ ){   //右边 
				for(int k=1;k<=r;k++){
					if(L[l][k]&&R[k][r])//左右区间可以合并
					{
						if(l==1&&r==n){
							printf("Yes\n");
							flag=true;
							break;	
						} 
						if(f[l-1][k]) R[l-1][r]=1;
						if(f[k][r+1]) L[l][r+1]=1;
					} 
				} 
			}
		}
		if(!flag)
			printf("No\n");
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值