CSP-J模拟赛1刘彦孜补题

日期:2024.10.2
学号:S06465
一:
总分数:
T1【交替出场 (alter)】:100
T2【翻翻转转(filp)】:0
T3【方格取数(square)】:70
T4【圆圆中的方方(round)】:20
二、比赛过程
第一题比较简单,为了保险,我用O(n^2)的思路做的
第二题做的时候没有思路,直接看的后面的题
第三题用的dp,基本上一直在挑错,修改
第四题根本不会,直接输出了样例偏分
三、比赛分析
T1【交替出场 (alter)】:
1.题目大意
给你一个字符串,让你求出字符串中01交替字串的个数
2.比赛中的思考
一层循环枚举左端点,第二层循环从左端点开始遍历,如果当前这一个字符和上一个相等,就跳出循环,否则就让计数器++,最后输出计数器
3.解题思路
枚举左端点,一位一位向右扩展判断
4.AC代码

#include<bits/stdc++.h>
using namespace std;
string s;
int ans;
int main(){
	cin>>s;
	int len=s.size();
	for(int i=0;i<len;i++){
		ans++;
		for(int j=i+1;j<len;j++){
			if(s[j]!=s[j-1]){
				ans++;
			}
			else{
				break;
			}
		}
	}
	printf("%d",ans);
	return 0;
}

T2【翻翻转转(filp)】:
1.题目大意
有一系列的字符串,s[i]是s[i-1]逐位取反后拼接在s[i-1]后的串,求无穷大的字符串中第x个字符是什么
2.比赛中的思考
比赛中没什么想法,直接放弃了
3.解题思路
用二分去做,每次分成两半,如果在左边就保持不变,如果在右边就取反1变0,0变1
4.AC代码

#include<bits/stdc++.h>
using namespace std;
int t,n;
int solve(int l,int r,int p){
	if(l==r){
		return p;
	}
	int mid=(l+r)>>1;
	if(n<=mid){
		return solve(l,mid,p);
	}
	return solve(mid+1,r,p^1);
}
int main(){
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		printf("%d\n",solve(1,1<<30,1));
	}
	return 0;
} 

1.题目大意
从(1,1)出发,走到(n,m),只能向右或者向下走,但是不能不能一次性往一个方向走大于等于k步,问收集到的数字的和的最大值
2.比赛中的思考
我用dp做,考虑是从哪个方向来的,和上一步是向哪走的,把两种方案都存下来
3.解题思路
用记忆化搜索会简单一些,x,y表示当前的位置,step表示连续走了几步,d表示我向哪走,然后根据两种情况(1.继续向这个走,2.向另一个方向走)dfs
4.AC代码

#include<bits/stdc++.h>
using namespace std;
const int N=205;
int n,m,k;
int a[N][N];
int dx[]={0,1};
int dy[]={1,0};
pair<int,bool> f[N][N][N][2];
int dfs(int x,int y,int step,int d){
	if (x>n||y>m||step>k){
		return -0x3f3f3f3f;
	}
	if(x==n&&y==m){
		return a[x][y];
	}
	if(f[x][y][step][d].second){
		return f[x][y][step][d].first;
	}
	f[x][y][step][d].second=1;
	int ans=-0x3f3f3f3f;
	if(step<k){
		ans=max(ans,dfs(x+dx[d],y+dy[d],step+1,d));
	}
	ans=max(ans,dfs(x+dx[d^1],y+dy[d^1],2,d^1));
	if(ans<-1e9){
		return f[x][y][step][d].first=-0x3f3f3f3f;
	}
	return f[x][y][step][d].first=ans+a[x][y];
}
int main(){
	scanf("%d%d%d",&n,&m,&k);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			scanf("%d",&a[i][j]);
		}
	}
	int tmp=max(dfs(1,2,2,0),dfs(2,1,2,1));
	if(tmp>-1e9){
		printf("%d",tmp+a[1][1]);
	}
	else{
		printf("No Answer!");
	}
	return 0; 
}

T4【圆圆中的方方(round)】:
1.题目大意
你有一个矩形。有一点 A(a,b),求以A为圆心,半径为r的圆与矩形的重叠部分的面积。
2.比赛中的思考
不知道怎么去做,直接输出了输出样例偏分
3.解题思路
可以把圆根据圆心分成四部分,在考虑每部分的情况,第一种情况是r<=n&&r<=m,第四种情况是完全重合,这两种直接计算就行,第二种情况是r>=m&&r<=n,第三种是r>=m&&r>=n但是没有完全重合的情况,这两种情况可以分成几部分并根据三角函数计算
4.AC代码

#include<bits/stdc++.h>
using namespace std;
const double pi=acos(-1),eps=1e-8;
double n,m,a,b,r;
double cal(double n,double m,double r){
	if(n<m){
		swap(n,m);
	}
	if(n<=eps||m<=eps){
		return 0;
	}
	if(r<=m){
		return 0.25*pi*r*r;
	}
	if(r>sqrt(n*n+m*m)){
		return n*m;
	}
	if(r<=n){
		return sqrt(r*r-m*m)*m*0.5+0.5*r*r*(0.5*pi-acos(m/r));
	}
	return sqrt(r*r-m*m)*m*0.5+sqrt(r*r-n*n)*n*0.5+0.5*r*r*(0.5*pi-acos(m/r)-acos(n/r));
}
int main(){
	cin>>n>>m>>a>>b>>r;
	printf("%lf",cal(a,b,r)+cal(n-a,b,r)+cal(a,m-b,r)+cal(n-a,m-b,r));
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值