日期:2024年10月1日
学号:S14738
一、我的总分:
T1【交替出场(alter)】:20分
T2【翻翻转转(filp)】:0分
T3【方格取数(square)】:0分
T4【圆圆中的方方(round)】:10分
二、比赛概况:
T1【交替出场(alter)】:
看完题倒是有点思路,但是觉得不太可行,毕竟n≤1000的时候三层循环不太现实(算下来最多得有10的9次方了吧),又想了想也没有别的思路了,就先打上代码了,后来也没有什么思路,就没有再改,最后也是成功拿到了20%数据的分数。
T2【翻翻转转(filp)】:
第一遍看完题觉得挺难的,后来在做的时候发现确实如此,就打的表(也没什么思路),在打了足足512个0和1以后(也就是第9个数),我觉得能得一点分,结果呢……嗯,0分。
T3【方格取数(square)】:
也是很难的一道题,然后直接跳过了,最后再看就没时间写代码了(还是没什么思路),匆匆忙忙cout了样例的答案,也没对。
T4【圆圆中的方方(round)】:
初一学生读完题表示比你还懵,学都没学过怎么算圆与矩形的重叠部分的面积,一看样例发现有一个可以骗分的地方,就cout了,但是只cout不给分啊啊!幸好后来又把分给我算上了。
三、比赛分析:
T1【交替出场(alter)】:
1、题目大意
给定一个字符串,仅包含字符 0
或 1
,求字符串中的 01
交替子串个数。
01
交替串的定义是,前一位必须不同于后一位的字符串。
特殊的,任意的长度为 1
的字符串也被定义为 01
交替串。
2、考试思路
就是循环:
01
交替串长度为 i
01
交替串从第 j 项开始
往后 i 位(判断能否形成01
交替串)
事实证明思路不对
3、讲解后思路
求从第 i 位开始的字符串个数,如果和上一位相等了就continue
4、AC代码
#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
int cnt;
string s;
int main(){
// freopen("alter.in","r",stdin);
// freopen("alter.out","w",stdout);
cin >> s;
int len = (int)s.size();
for(int i = 0;i < len;i++){
//任意的长度为 1 的字符串也被定义为 01 交替串,cnt要加上长度为 1 字符串数量
cnt++;
for(int j = i+1;j < len;j++){
//01 交替串的定义是,前一位必须不同于后一位的字符串,所以 s[j] 不能等于 s[j-1]
if(s[j] != s[j-1]){
cnt++;
}else{
break;
}
}
}
cout << cnt;
// fclose(stdin);
// fclose(stdout);
return 0;
}
T2【翻翻转转(filp)】:
1、题目大意
gza 有一系列的字符串,第 ii 个名为 s_isi。
s_0 = 1
s_1 = 10
s_2 = 1001
s_3 = 10010110
⋯⋯
s_i 是s_i−1 逐位取反后拼接在 s_i−1 后的串。
你需要求s_114514 的第 x 个字符是什么。
多测。
2、考试思路
没有思路,就想着打表呗,最后也没得分
3、讲解后思路
类似二分查找思路,在左边不改,在右边按位取反,直到找到答案
4、AC代码
#include<iostream>
#include<cstdio>
using namespace std;
int t,x;
void fun(int l,int r,bool p){
//l==r 说明找到了答案,直接输出
if(l == r){
cout << (p == true ? 1 : 0) << endl;
return;
}
int mid = (l+r)/2;
//二分算法
if(x<= mid){
fun(l,mid,p);
}else{
//!p是因为右半边要按位取反
fun(mid+1,r,!p);
}
}
int main(){
// freopen("filp.in","r",stdin);
// freopen("filp.out","w",stdout);
cin >> t;
while(t--){
cin >> x;
//1 << 30表示将数字1的二进制形式左移30位,转换为十进制后等于2^30
fun(1,1 << 30,1);
}
// fclose(stdin);
// fclose(stdout);
return 0;
}
T3【方格取数(square)】:
1、题目大意
想必大家都做过方格取数吧。
现在,你需要做一个特殊的方格取数。
每个格子都有一个数字,走过便能收集,也必须收集。
你从 (1,1)(1,1) 出发,目标是 (n,m)(n,m),只能向右或者向下走,但是你不能一次性往一个方向走大于等于 kk 步。
求收集到的数字的和的最大值。
如果无解,输出“No Answer!
”
2、考试思路
感觉dfs可以,但是有了步数限制就是不知道怎么实现
3、讲解后思路
要用到四层循环和四维数组,确实是dfs的思路(移动->判断出界->判断状态->赋值)
4、AC代码
#include<bits/stdc++.h>
using namespace std;
long long f[210][210][210][2],a[210][210];
int n,m,k;
int dx[2] = {0,1};
int dy[2] = {1,0};
int main(){
// freopen("square.in","r",stdin);
// freopen("square.out","w",stdout);
cin >> n >> m >> k;
for(int i = 1;i <= n;i++){
for(int j = 1;j <= m;j++){
cin >> a[i][j];
}
}
memset(f,-0x3f,sizeof f);
f[1][1][0][0] = f[1][1][0][1] = a[1][1];
for(int i = 1;i <= n;i++){
for(int j = 1;j <= m;j++){
for(int l = 0;l < k;l++){
for(int d = 0;d <= 1;d++){
//没有对应状态
if(f[i][j][l][d] < -4e9){
continue;
}
for(int dd = 0;dd <= 1;dd++){
//移动
int x = i+dx[dd];
int y = j+dy[dd];
//判断出界
if(x>n || y>m){
continue;
}
//这一次移动的位置与上一次是否相同并对相应状态赋值
if(d!=dd){
f[x][y][1][dd] = max(f[x][y][1][dd],f[i][j][l][d]+a[x][y]);
}else{
f[x][y][l+1][dd] = max(f[x][y][l+1][dd],f[i][j][l][dd]+a[x][y]);
}
}
}
}
}
}
long long maxx = -4e9;
for(int l = 0;l < k;l++){
for(int d = 0;d <= 1;d++){
maxx = max(maxx,f[n][m][l][d]);
}
}
if(maxx == -4e9){
cout << "No Answer!";
}else{
cout << maxx;
}
// fclose(stdin);
// fclose(stdout);
return 0;
}
T4【圆圆中的方方(round)】:
1、题目大意
你有一个四个边界点为 (0,0),(n,0),(0,m),(n,m) 的矩形。
有一点 A(a,b) 保证 A 在矩形内部或边界上,求以 A 为圆心,半径为 r 的圆与矩形的重叠部分的面积。
2、考试思路
我真没学过,不会,单纯就骗个10分
3、讲解后思路
要用到三角函数(如图),代码很麻烦,分很多种情况,要一个一个判断
4、AC代码
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
const double eps = 1e-8;
double S(double x,double y,double r){
if(x<eps || y<eps){
return 0;
}
//判断 x > r 且 y > r ,取圆面积的四分之一
if(x > r && y > r){
return (M_PI*r*r)/4;
}
//其他情况将圆与矩形的重叠部分的面积分成三角形和扇形分别计算
if(x > r){
double x_ = sqrt(r*r-y*y);
double ang = atan(y / x_);
return ang/2*r*r+y*x_/2;
}else if(y > r){
double y_ = sqrt(r*r-x*x);
double ang = atan(x / y_);
return ang/2*r*r+x*y_/2;
}
double x_ = sqrt(r*r-y*y);
if(x_ > x){
return x*y;
}
double ang1 = atan(x_/y);
double y_ = sqrt(r*r-x*x);
double ang2 = atan(y_/x);
double ang = M_PI/2-ang1-ang2;
return (ang/2*r*r)+x*y_/+y*x_/2;
}
int main(){
// freopen("round.in","r",stdin);
// freopen("round.out","w",stdout);
double n,m,a,b,r;
cin >> n >> m >> a >> b >> r;
//圆的上下左右四部分面积和
double ans = S(n-a,m-b,r)+S(a,m-b,r)+S(a,b,r)+S(n-a,b,r);
printf("%.10lf\n",ans);
// fclose(stdin);
// fclose(stdout);
return 0;
}
四、反思&总结:
能写代码写代码,尽量不要去骗分