[蓝桥杯 2020 省 B2] 平面切分
题目描述
平面上有 N 条直线, 其中第 i 条直线是 y=Ai⋅x+Bi 。请计算这些直线将平面分成了几个部分。
输入格式
第一行包含一个整数 N。
以下 N 行, 每行包含两个整数 Ai,Bi。
输出格式
一个整数代表答案。
代码表示
#include<bits/stdc++.h>
#define PDD pair<long double,long double>
using namespace std;
const int N = 1e3+5;//直线的最大数量
int n,ans;
long double a[N],b[N];
bool vis[N];//标记第i条直线是否与其他直线重合
int main()
{cin>>n;for(int i = 1;i<=n;i++){cin>>a[i]>>b[i];set<PDD> s;//使用pair记录横坐标、纵坐标 s.clear();//清理集合 for (int j = 1;j<i;j++){if(vis[j])//与前面的直线重合,跳过 continue;if(a[i]==a[j]&&b[i]==b[j]){vis[i] = 1;//标记 break;}if(a[i]==a[j])//斜率一样,i平行与j,无交点continue;//算交点将其插入集合ss.insert({(b[i]-b[j])/(a[j]-a[i]),(a[j]*b[i]-a[i]*b[j])/(a[j]-a[i])});}if(!vis[i])//当第i条直线不与前面的直线重合时才统计 ans+=s.size()+1;}cout<<ans+1;//初始平面有一部分 return 0;
}
心得体会
如上图,先有 4根绿色的线,然后又来了一根黑色的线,与之前绿色的线共有 4个交点。将原来的 5个部分,一分为二,即又新增了 5个部分(分别是 1 , 2 , 3 , 4 , 5 )。
我们可以得出一个结论:如果新来的一条直线 与 已有的直线有 t个交点,那么就会增加 t + 1 个部分。
1、首先,定义了一个常量N表示直线的最大数量,并声明了一些变量和数据结构,包括整数n表示直线的数量,整数ans表示答案,数组a和b分别用于存储直线的斜率和截距,以及一个布尔数组vis用于标记直线是否与其他直线重合。
2、通过输入读取N的值,然后使用for循环遍历每一条直线,从1到n。
3、在循环中,首先通过输入读取直线的斜率a[i]和截距b[i]。
4、创建一个空的集合s,用于存储交点的坐标。集合中的每个元素都是一个pair<long double, long double>,分别表示交点的x坐标和y坐标。
5、在内层循环中,使用for循环遍历之前的直线,从1到i-1。
1)如果vis[j]为true,表示直线j与之前的某条直线重合,跳过当前循环。
2)如果a[i]等于a[j]且b[i]等于b[j],表示直线i与直线j完全重合,将vis[i]标记为true,并跳出内层循环。
3)如果a[i]等于a[j],表示直线i与直线j平行,没有交点,跳过当前循环。
4)否则,计算直线i和直线j的交点坐标,并将交点插入集合s中。交点的x坐标为(b[i]-b[j])/(a[j]-a[i]),y坐标为(a[j]*b[i]-a[i]*b[j])/(a[j]-a[i])。
5、如果直线i不与之前的任何直线重合(即vis[i]为false),则统计集合s的大小,并将结果加到ans上
[蓝桥杯 2018 省 A] 航班时间
题目描述
小 h 前往美国参加了蓝桥杯国际赛。小 h 的女朋友发现小 h 上午十点出发,上午十二点到达美国,于是感叹到“现在飞机飞得真快,两小时就能到美国了”。
小 h 对超音速飞行感到十分恐惧。仔细观察后发现飞机的起降时间都是当地时间。由于北京和美国东部有 12小时时差,故飞机总共需要 14小时的飞行时间。
不久后小 h 的女朋友去中东交换。小 h 并不知道中东与北京的时差。但是小 h 得到了女朋友来回航班的起降时间。小 h 想知道女朋友的航班飞行时间是多少。
对于一个可能跨时区的航班,给定来回程的起降时间。假设飞机来回飞行时间相同,求飞机的飞行时间。
输入格式
从标准输入读入数据。一个输入包含多组数据。输入第一行为一个正整数 T,表示输入数据组数。
每组数据包含两行,第一行为去程的起降时间,第二行为回程的起降时间。起降时间的格式如下
h1:m1:s1 h2:m2:s2
或h1:m1:s1 h3:m3:s3 (+1)
或h1:m1:s1 h4:m4:s4 (+2)
表示该航班在当地时间 h1
时 m1
分 s1
秒起飞,
第一种格式表示在当地时间 当日 h2
时 m2
分 s2
秒降落
第二种格式表示在当地时间 次日 h3
时 m3
分 s3
秒降落。
第三种格式表示在当地时间 第三天 h4
时 m4
分 s4
秒降落。
对于此题目中的所有以 h:m:s
形式给出的时间, 保证(0≤h≤23,0≤m,s≤59).
输出格式
输出到标准输出。
对于每一组数据输出一行一个时间 hh:mm:ss
,表示飞行时间为 hh
小时 mm
分 ss
秒。
注意,当时间为一位数时,要补齐前导零。如三小时四分五秒应写为 03:04:05
。
代码表示
#include<bits/stdc++.h>
using namespace std;int get()
{int h1,m1,s1,h2,m2,s2,d=0;scanf("%d:%d:%d %d:%d:%d",&h1,&m1,&s1,&h2,&m2,&s2);if(getchar()==' ')scanf("(+%d)",&d);return (d*86400+h2*3600+m2*60+s2)-(h1*3600+m1*60+s1);
}
int main()
{int T;scanf("%d",&T);while(T--){int ans=(get()+get())/2;printf("%02d:%02d:%02d\n",ans/3600,ans%3600/60,ans%60);}return 0;
}
思路提示
这道题的输入,输出,转换,都值得再看
[蓝桥杯 2015 省 A] 饮料换购
题目描述
乐羊羊饮料厂正在举办一次促销优惠活动。乐羊羊 C 型饮料,凭 3 个瓶盖可以再换一瓶 C 型饮料,并且可以一直循环下去(但不允许暂借或赊账)。
请你计算一下,如果小明不浪费瓶盖,尽量地参加活动,那么,对于他初始买入的 n 瓶饮料,最后他一共能喝到多少瓶饮料。
输入格式
一个整数 n,表示开始购买的饮料数量。(0<n<10000)
输出格式
一个整数,表示实际得到的饮料数。
心得体会
数学问题,重点在于整个循环,并且要更新n的值,一开始的问题是没有加上n取余的数余下的数下一次循环算的时候也应当算进去。
代码表示
#include<bits/stdc++.h>
using namespace std;int main()
{int n;cin>>n;int num=n;while(n>=3){num+=n/3;n=n/3+n%3;}cout<<num;return 0;
}
[蓝桥杯 2020 省 AB1] 走方格
题目描述
在平面上有一些二维的点阵。这些点的编号就像二维数组的编号一样,从上到下依次为第 1至第 n 行,从左到右依次为第 1至第 m 列,每一个点可以用行号和列号来表示。
现在有个人站在第 1行第 1列,要走到第 n 行第 m 列。只能向右或者向下走。
注意,如果行号和列数都是偶数,不能走入这一格中。
问有多少种方案。
输入格式
输入一行包含两个整数 n,m。
输出格式
输出一个整数,表示答案。
代码表示
#include <bits/stdc++.h>
using namespace std;int uniquePaths(int m, int n) {vector<vector<int> > dp(m, vector<int>(n, 0));for (int i = 0; i < m; i++) dp[i][0] = 1;for (int j = 0; j < n; j++) dp[0][j] = 1;for (int i = 1; i < m; i++){for (int j = 1; j < n; j++){if((i-1)%2!=0||(j-1)%2!=0)dp[i][j] = dp[i - 1][j] + dp[i][j - 1];}}return dp[m - 1][n - 1];
}int main() {int m,n;cin>>m>>n;cout<<uniquePaths(m,n);return 0;
}
心得体会
这道题就是在Day42中的不同路径Ⅰ的改版!!!就加了一个判断是不是偶数格。
所以动规的题还是要好好练习!!
[蓝桥杯 2020 省 AB3] 乘法表
题目描述
九九乘法表是学习乘法时必须要掌握的。在不同进制数下,需要不同的乘法表。
例如, 四进制下的乘法表如下所示:
1*1=1
2*1=2 2*2=10
3*1=3 3*2=12 3*3=21
请注意,乘法表中两个数相乘的顺序必须为样例中所示的顺序,不能随意交换两个乘数。
给定 P,请输出 P 进制下的乘法表。
输入格式
输入一个整数 P。
输出格式
输出 P 进制下的乘法表。P 进制中大于等于 10 的数字用大写字母 A
、B
、C
、⋯⋯ 表示。
代码表示
#include <bits/stdc++.h>
using namespace std;int main() {int n,k;cin>>n;for(int i=1;i<n;++i){for(int j=1;j<=i;++j){if((i*j)/n==0){cout<<i<<"*"<<j<<"="<<(i*j)%n<<" ";}else{cout<<i<<"*"<<j<<"="<<(i*j)/n<<(i*j)%n<<" ";}}cout<<"\n";}return 0;
}
心得体会
但只有30分,明明测试点都可以,但就是不行
这是满分答案:
#include<bits/stdc++.h>
using namespace std;
int n;
string jz(int x, int y)//把x转换为y进制
{string now, ret;while (x > 0){int add = x % y; // 记录余数if (add >= 10) // 余数大于等于10的要变为字母now += add - 10 + 'A'; // 余数加上 'A'的ASCII值减去10将其转换为字母elsenow += add + '0'; // 余数加上 '0'的ASCII将其转换为数字字符x /= y; // 将 x 除以 y,继续处理下一位}int len = now.size(); // 获取转换后的字符串长度for (int i = 0; i <= len / 2; i++) // 倒着存储转换后的字符串ret += now[len - i - 1];return ret; // 返回转换后的结果
}int main()
{cin>>n;for(int i = 1;i<n;i++){for(int j = 1;j<=i;j++){cout<<jz(i,n)<<'*'<<jz(j,n)<<'='<<jz(i*j,n)<<' ';//记得转换进制}cout<<'\n';}return 0;
}
[蓝桥杯 2018 省 AB] 全球变暖
题目描述
你有一张某海域N×N 像素的照片,.
表示海洋、 #
表示陆地,如下所示:
.......
.##....
.##....
....##.
..####.
...###.
.......
其中 "上下左右" 四个方向上连在一起的一片陆地组成一座岛屿。例如上图就有 2座岛屿。由于全球变暖导致了海面上升,科学家预测未来几十年,岛屿边缘一个像素的范围会被海水淹没。具体来说如果一块陆地像素与海洋相邻(上下左右四个相邻像素中有海洋),它就会被淹没。
例如上图中的海域未来会变成如下样子:
.......
.......
.......
.......
....#..
.......
.......
请你计算:依照科学家的预测,照片中有多少岛屿会被完全淹没。
输入格式
第一行包含一个整数 N。(1≤N≤1000)。
以下 N 行 N 列代表一张海域照片。
照片保证第 1 行、第 1 列、第 N 行、第 N 列的像素都是海洋。
输出格式
一个整数表示答案。
代码表示
#include<bits/stdc++.h>
using namespace std;
//dx 和 dy 是用来表示四个方向的数组,mp是地图
//t 是一个标志变量 cnt 是用于计数的变量,sum 是岛屿的总数量,ans 是没被淹没的岛屿数量
int n,cnt,sum,ans,t,dx[]={0,1,0,-1},dy[]={1,0,-1,0};
char mp[1010][1010];
void dfs(int x,int y)//深度优先遍历
{if(!t)//如果为 0,则表示当前陆地像素与海洋相邻//一块陆地像素与海洋相邻(上下左右四个相邻像素中有海洋),就会被淹没。{cnt=0;for(int i=0;i<4;i++)//遍历四个相邻像素if(mp[x+dx[i]][y+dy[i]]!='.') cnt++;if(cnt==4)//岛屿上的一个点四周无海洋ans++,t=1;//这个岛屿不会被淹没}mp[x][y]='*';//标记已经访问过for(int i=0;i<4;i++){//判断相邻位置是否越界或者不是陆地(#)int xx=x+dx[i],yy=y+dy[i];if(xx<0||xx>=n||yy<0||yy>=n||mp[xx][yy]!='#') continue;//跳过当前循环dfs(xx,yy);//递归调用 dfs 函数,继续搜索下一个位置}
}
int main()
{cin>>n;
//通过两个嵌套的循环读取岛屿的地图,并将其存储在 mp 数组中for(int i=0;i<n;i++)for(int j=0;j<n;j++)cin>>mp[i][j];//遍历 mp 数组中除去边界的位置,如果当前位置是陆地(#),则增加 sum 的值
//并将 t 的值设为 0,然后调用 dfs 函数for(int i=1;i<n-1;i++)for(int j=1;j<n-1;j++)if(mp[i][j]=='#'){sum++;t=0;dfs(i,j);}cout<<sum-ans;//岛屿总数量-没被淹没的岛屿
}
心得体会
这段代码的中心思想是通过深度优先搜索(DFS)来统计岛屿的数量,并计算没有被淹没的岛屿数量。
算法步骤如下:
1、读取岛屿的大小 n
和岛屿的地图,将地图存储在字符数组 mp
中。
2、遍历 mp
数组中除去边界的位置,对于每个位置,如果是陆地(#
),则进行以下操作:
1)增加岛屿的总数量 sum
。
2)将标志变量 t
的值设为 0。
3)调用深度优先搜索函数 dfs
,对当前位置进行搜索。
3、在 dfs
函数中,首先判断当前陆地像素点是否与海洋相邻,如果相邻,则判断当前位置是否会被淹没:
1)通过遍历当前位置的四个相邻像素,计算相邻海洋的数量。如果数量为 4,表示该岛屿的一个点四周都没有海洋,那么这个岛屿不会被淹没,增加没被淹没的岛屿数量 ans
,将 t
的值设为 1。
2)将当前位置的 mp
数组值标记为 *
,表示已经访问过。
3)继续递归调用 dfs
函数,对当前位置的四个相邻位置进行搜索。
4、最后,输出岛屿的总数量减去没有被淹没的岛屿数量,即 sum - ans
。