蓝桥杯刷题计划(C/C++B组)

142 阅读7分钟

01题 X进制减法 2022 省赛E题

题目描述

image.png

image.png

Code

using namespace std; 
const int M=1e5,mod=1e9+7;
typedef long long ll;
int n;  //最高进制n 
int A,B;//A B两数位数 
int Ma,Mb;//A B两数十进制数 
int a[M],b[M],w[M];
int x;//最高位数 
int mul=0;
int main()
{
	cin>>n;
	cin>>A;
	for(int i=A-1;i>=0;i--){
		cin>>a[i];
	}
	cin>>B;
	for(int i=B-1;i>=0;i--){
		cin>>b[i];
	}
	//数组中低位存储进制数低位 
	if(A!=B&&A<n&&B<n) 
		x=(A>=B)?A:B;
	else
		x=A; 
	//保存每位的j进制  最低位为二进制 
	w[0]=2;
	int wgt=1; //记录权重 
	for(int i=1;i<x;i++){
		a[i]>b[i]?w[i]=a[i]+1:w[i]=b[i]+1;
	}
	for(int i=0;i<x;i++){
		mul+=(a[i]-b[i])*wgt;
		wgt*=w[i];
	} 
	cout<<mul;
	return 0;
} 

注意事项

  1. 理解进制的概念,本题易错在计算每位的权重上,十进制381=3×10×10+8×10+1×1,而在本题的X进制中381(X)=3×9×2+8×2+1×1=71(10),切勿理解为381(X)=3×90+8×20+1×1=431(10)。
  2. 贪心算法:数的每位都选用对A和B来说合理的进制最小但不低于2的进制,A-B的值最小。就比如第i位,A的数为3,B的数为4,对A来说进制最小为4,对B来说进制最小为5,那么对A和B来说该位合理的进制最小为5。每位的进制得出来后,再算出每位的权值。

02题 日期位数之和 2023 模拟赛第三期C题

问题描述

对于一个日期,我们可以计算出年份的各个数位上的数字之和,也可以分别计算月和日的各位数字之和。请问从 1900 年 1 月 1 日至 9999 年 12 月 31 日,总共有多少天,年份的数位数字之和等于月的数位数字之和加日的数位数字之和。 例如,2022年11月13日满足要求,因为 2+0+2+2=(1+1)+(1+3) 。 请提交满足条件的日期的总数量。

答案:70910

模板总结

  1. 计算日期之间的天数(判断闰年)
int month[13][2]={{0,0},{31,31},{28,29},{31,31},{30,30},{31,31},{30,30},{31,31},{31,31},{30,30},{31,31},{30,30},{31,31}};
bool isLeap(int year)
{
	return (year%4==0 && year%100!=0) || (year%400==0);
}
int main(){
	int time1,y1,m1,d1;
	int time2,y2,m2,d2;
	int ans=0;
	scanf("%d%d",&time1,&time2);
	if(time1>time2){
			int tmp=time1;
			time1=time2;
			time2=tmp;
		}
		y1=time1/10000,m1=time1%10000/100,d1=time1%100;
		y2=time2/10000,m2=time2%10000/100,d2=time2%100;
		while(y1<y2 || m1<m2 || d1<d2) {
			d1++;
			if(d1==month[m1][isLeap(y1)]+1) { //满月天数 
				m1++;
				d1=1;
			}
			if(m1==13) {
				y1++;
				m1=1;
			}
			ans++;
		}
		cout<<ans;
	return 0;
}
  1. 分解位数(较小位数的数字),在数字位数较大的情况下应转化为字符串处理
                        int tmp1=y1,tmp2=m1,tmp3=d1;
			int sum1=0,sum2=0;
			while(tmp1){
				sum1+=tmp1%10;
				tmp1/=10;
			}
			for(int i=0;i<2;i++){
				sum2+=tmp2%10+tmp3%10;
				tmp2/=10;
				tmp3/=10;
			}

Code

#include<bits/stdc++.h>
using namespace std;
int month[13][2]={{0,0},{31,31},{28,29},{31,31},{30,30},{31,31},{30,30},{31,31},{31,31},{30,30},{31,31},{30,30},{31,31}};
bool isLeap(int year)
{
	return (year%4==0 && year%100!=0) || (year%400==0);
}
int main(){
	int time1,y1,m1,d1;
	int time2,y2,m2,d2;
	int ans=0;
	scanf("%d%d",&time1,&time2);
	if(time1>time2){
			int tmp=time1;
			time1=time2;
			time2=tmp;
		}
		y1=time1/10000,m1=time1%10000/100,d1=time1%100;
		y2=time2/10000,m2=time2%10000/100,d2=time2%100;
		while(y1<y2 || m1<m2 || d1<d2) {
			d1++;
			if(d1==month[m1][isLeap(y1)]+1) { //满月天数 
				m1++;
				d1=1;
			}
			if(m1==13) {
				y1++;
				m1=1;
			}
			int tmp1=y1,tmp2=m1,tmp3=d1;
			int sum1=0,sum2=0;
			while(tmp1){
				sum1+=tmp1%10;
				tmp1/=10;
			}
			for(int i=0;i<2;i++){
				sum2+=tmp2%10+tmp3%10;
				tmp2/=10;
				tmp3/=10;
			}
			if(sum1==sum2){
				ans++;
			}
		}
		cout<<ans;
	return 0;
}

03题 信号塔检测 2023 模拟赛第三期G题

问题描述

小蓝负责一块区域的信号塔安装,整块区域是一个长方形区域,建立坐标轴后,西南角坐标为 (0, 0), 东南角坐标为 (W, 0), 西北角坐标为 (0, H), 东北角坐标为 (W, H)。其中 W, H 都是整数。 他在 n 个位置设置了信号塔,每个信号塔可以覆盖以自己为圆心,半径为 R 的圆形(包括边缘)。 为了对信号覆盖的情况进行检查,小蓝打算在区域内的所有横纵坐标为整数的点进行测试,检查信号状态。其中横坐标范围为 0 到 W,纵坐标范围为 0 到 H,总共测试 (W+1) * (H+1) 个点。 给定信号塔的位置,请问这 (W+1)*(H+1) 个点中有多少个点被信号覆盖。

输入格式 输入第一行包含四个整数 W, H, n, R,相邻整数之间使用一个空格分隔。 接下来 n 行,每行包含两个整数 x, y,表示一个信号塔的坐标。信号塔可能重合,表示两个信号发射器装在了同一个位置。

输出格式 输出一行包含一个整数,表示答案。

样例输入

10 10 2 5
0 0
7 0

样例输出

57

评测用例规模与约定 对于所有评测用例,1 <= W, H <= 100,1 <= n <= 100, 1 <= R <= 100, 0 <= x <= W, 0 <= y <= H。

Code

#include<bits/stdc++.h>
using namespace std;
const int maxn=105;
int W,H,n,R,ans,x,y;
bool vis[maxn][maxn];
void judge()
{
	for(int i=0;i<=W;i++){
		for(int j=0;j<=H;j++){
			if(!vis[i][j] && (x-i)*(x-i)+(y-j)*(y-j)<=R*R){
				vis[i][j]=true;
				ans++;
			}
		}
	}
} 
int main()
{
	cin>>W>>H>>n>>R;
	for(int i=0;i<n;i++){
		cin>>x>>y;
		judge();
	}
	cout<<ans;
	return 0;
}

注意事项

  1. 本题只需要统计最后的个数,不需要将数据记录下来
  2. 注意记忆只需访问未被信号覆盖的点,减少搜索量

04题 网格压缩 2023 成都大学contest 5 A题

问题描述:

给出H×W的图,如果这个图上一行或一列没有#的话将这一行或这一列删除,输出处理完后的图。1<=H,W<=100

输入描述:

H W
a1,1...a1W
.
.
aH,1...aH,W

输出描述:

打印出处理完后的图

样例输入

4 4
##.#
....
##.#
.#.#

样例输出

###
###
.##

Code

#include <iostream>
#include <vector>
using namespace std;

int main() {
    int H, W;
    cin >> H >> W;
    vector<vector<char> > board(H, vector<char>(W)); // 储存图
    vector<bool> row(H, false); // 行是否有 #
    vector<bool> col(W, false); // 列是否有 #
    for (int i = 0; i < H; i++) {
        for (int j = 0; j < W; j++) {
            cin >> board[i][j];
            if (board[i][j] == '#') { // 如果这个位置有 #
                row[i] = true;
                col[j] = true;
            }
        }
    }
    for (int i = 0; i < H; i++) {
        if (row[i]) { // 如果这一行有 #
            for (int j = 0; j < W; j++) {
                if(col[j]) { // 如果这一列有 #
                    cout << board[i][j];
                }
            }
            cout << endl;
        }
    }
    return 0;
}

05题 跳出实验室 2023 成都大学contest5 B题

问题描述

该情景可抽象在线性坐标系中,小华在跳出实验室时遇到了一扇门需要打开。
这扇门有N个开关,第i个开关在坐标xi处,一开始小华在坐标0处。
当打开至少K个开关时,这扇门就会打开。
如果Lin的移动速度为1,打开开关忽略不计,问小华至少要花费多少时间才能使这扇门打开。

样例输入

N K
x1 x2 ... xn

样例输出

40

Code

06题 轻重搭配

问题描述

某一天,zxl 和 rys 一起去动物园参观,他们来到了售票处正好有一个符合他们体重的活动正在进行。  一共有 n 个同学去动物园参观,原本每人都需要买一张门票,但售票处推出了一个优惠活动,一个体重为 x 的人可以和体重至少为 2·x 配对,这样两人只需买一张票。现在给出了 n 个人的体重,请你计算他们最少需要买几张门票?

类型

二分 贪心

Code

#include <bits/stdc++.h>
using namespace std;
int a[500005];
int main() {
	int n;
	cin>>n;
	for (int i = 0; i < n; i++) {
		cin>>a[i];
	}
	sort(a, a + n);
	int ans = n, pos = n / 2;
	for (int i = 0; i < n / 2; i++) {
		while (pos < n && a[pos] < a[i] * 2) pos++;
		if (pos == n) break;
		ans--;
		pos++;
	}
	cout<<ans;
	return 0;
}

07题 月饼 PAT B1020

类型

贪心 排序 结构体

题目描述

image.png image.png 样例输入 image.png

Code

#include<bits/stdc++.h>
using namespace std;
struct mooncake {
	double store;
	double sell;
	double price;
}cake[1010];
bool cmp(mooncake a,mooncake b){
	return a.price>b.price;
}
int main()
{
	int n;
	double D;
	cin>>n>>D;
	for(int i=0;i<n;i++){
		cin>>cake[i].store;
	}
	for(int i=0;i<n;i++){
		cin>>cake[i].sell;
		cake[i].price=cake[i].sell/cake[i].store;
	}
	sort(cake,cake+n,cmp);
	double ans=0;
	for(int i=0;i<n;i++){
		if(cake[i].store<=D){
			D-=cake[i].store;
			ans+=cake[i].sell;
		}else{
			ans+=cake[i].price*D;
			break;
		}
	}
	printf("%.2f\n",ans);
	return 0;
 } 

08题 不交区间

类型

区间贪心

题目描述

image.png

Code

#include<bits/stdc++.h>
using namespace std;
const int maxn=110;
struct Inteval {
	int x,y;//区间左右端点
} I[maxn];
bool cmp(Inteval a,Inteval b) {
	if(a.x!=b.x) return a.x>b.x;
	else return a.y<b.y;
}
int main() {
	int n;
	while(cin>>n,n!=0) {
		for(int i=0; i<n; i++) {
			cin>>I[i].x>>I[i].y;
		}
		sort(I,I+n,cmp);
		int ans=1,lastX=I[0].x;
		for(int i=1; i<n; i++) {
			if(I[i].y<=lastX) {//如果该区间右端点在lastX左边 
				lastX=I[i].x;
				ans++;
			}
		}
		cout<<ans<<endl;
	}
	return 0;
}

09题 01背包问题

类型

贪心 DFS

题目描述

image.png 样例输入

5 8
3 5 1 2 2
4 5 2 1 3

样例输出

10

Code

#include<bits/stdc++.h>
using namespace std;
const int maxn=30;
int n,V,maxValue=0;   //物品件数,背包容量,最大价值
int w[maxn],c[maxn];  //每件物品重量,每件物品价值 
//sumW和sumC为当前总重量和总价值
void DFS(int index, int sumW, int sumC)
{
	if(index==n){
		if(sumW<=V&&sumC>maxValue){
			maxValue=sumC;
		}
		return;
	}
	//选择
	DFS(index+1,sumW,sumC);                      //不选第index件物品 
	DFS(index+1,sumW+w[index],sumC+c[index]);    //选第index件物品 
 } 
int main()
{
	cin>>n>>V;
	for(int i=0;i<n;i++){
		cin>>w[i];
	} 
	for(int i=0;i<n;i++){
		cin>>c[i];
	} 
	DFS(0,0,0);
	cout<<maxValue;
	return 0;	
}

优化

由于每件物品都有两种选择,因此上述代码时间复杂度为O(2^n)。在上述代码中,总是把n件物品全部选择后才去更新最大价值,事实上忽略了背包容量不超过V这个特点,也就是说可以把对sumV的判断加入“岔道口”中,只有当sumV<=V时才进入岔道。这种通过题目条件来减少DFS计算量的方法称为“剪枝”。

 void DFS(int index, int sumW, int sumC)
 {
 	if(index==n){
 		return;
	 }
	 DFS(index+1, sumW, sumC);
	 if(sumW+w[index]<=V){
	 	if(sumC+c[index]>maxValue){
	 		maxValue=sumC+c[index];
		 }
		 DFS(index+1,sumW+w[index],sumC+c[index]);
	 }
 }

10题 数塔问题

题目描述

image.png

样例输入

5
5
8 3
12 7 16
4 10 11 6
9 5 3 9 4

样例输出

44

类型

动态规划:
一个问题可以分解为若干个子问题,且这些子问题会重复出现,称这个问题拥有重叠子问题
一个问题的最优解,可以由其子问题的最优解有效构造出来,称为这个问题拥有最优子结构
一个问题拥有重叠子问题最优子结构才能用动态规划解决问题

  1. 定义状态
  2. 定义状态转移方程
  3. 定义边界
  4. 求解问题

Code

递推实现 自底向上

#include<bits/stdc++.h>
using namespace std;
const int maxn=1000;
int f[maxn][maxn], dp[maxn][maxn];
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=i;j++){
			cin>>f[i][j];
		}
	}
	//边界
	for(int i=1;i<=n;i++){
		dp[n][i]=f[n][i];
	} 
	for(int i=n-1;i>=1;i--){
		for(int j=1;j<=i;j++){
			//状态转移方程
			dp[i][j]=max(dp[i+1][j], dp[i+1][j+1])+f[i][j];
		}
	}
	cout<<dp[1][1]<<endl;
	return 0;
 } 

递归实现 自顶向下

#include<bits/stdc++.h>
using namespace std;
const int maxn=1000;
int f[maxn][maxn], dp[maxn][maxn];
int n;
int Fn(int x,int y)
{
    //边界
    if(x==n) return f[x][y];
    if(dp[x][y]!=-1) return dp[x][y];
    else{
        dp[x][y]=max(Fn(x+1,y), Fn(x+1,y+1) )+f[x][y];//状态转移方程
        return dp[x][y];
    }
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=i;j++){
            cin>>f[i][j];
        }
    }
    //初始化 dp数组 
    memset(dp, -1, sizeof(dp));
    //边界
    for(int i=1;i<=n;i++){
        dp[n][i]=f[n][i];
    } 
    int ans=Fn(1,1);
    cout<<ans<<endl;
    return 0;
} 

11题 最大连续子序列和

题目描述

image.png

样例输入

 6
 -2 11 -4 13 -5 -2

样例输出

20

Code

递归实现

#include<bits/stdc++.h>
using namespace std;
const int maxn=10010;
int f[maxn], dp[maxn];
int Fn(int x)
{
	if(x==0) return f[0];
	if(dp[x]!=-1) return dp[x];
	else{
		dp[x]=max(f[x], Fn(x-1)+f[x]);//状态转移方程
		return dp[x];
	} 
}
int main()
{
	int n;
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>f[i];
	}
	memset(dp, -1, sizeof(dp));
	//边界条件 
	dp[0]=f[0];
	Fn(n);
	int k=0;
	for(int i=0;i<n;i++){
		if(dp[i]>dp[k])
			k=i;
	}
	cout<<dp[k]<<endl;
	return 0;
}

12题 最长不下降子序列(LIS)

问题描述

image.png

样例输入

8
1 2 3 -9 3 9 0 11

样例输出

6

Code

#include<bits/stdc++.h>
using namespace std;
const int maxn=100;
int f[maxn], dp[maxn];
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>f[i];
	}
	int ans=-1;
	for(int i=1;i<=n;i++){
		dp[i]=1;//边界初始条件
		for(int j=1;j<i;j++){
			if(f[j]<=f[i] && (dp[j]+1>dp[i])){
				dp[i]=dp[j]+1;//状态转移方程
			}
		}
		ans=max(ans,dp[i]);
	}
	cout<<ans<<endl;
	return 0;
} 

13题 最长公共子序列(LCS)

题目描述

image.png 样例输入

sadstory
adminsorry

样例输出

6

Code

#include<bits/stdc++.h>
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 100;
char A[N], B[N];
int dp[N][N];
int main()
{
	gets(A+1);
	gets(B+1);
	int lenA = strlen(A + 1);
	int lenB = strlen(B + 1);
	//边界
	for(int i=0; i<=lenA; i++){
		dp[i][0]=0;
	} 
	for(int j=0; j<=lenB; j++){
		dp[0][j]=0;
	} 
	//状态转移方程
	for(int i=1; i<=lenA; i++){
		for(int j=1; j<=lenB; j++){
			if(A[i] == B[j]){
				dp[i][j]=dp[i-1][j-1]+1;
			}else{
				dp[i][j]=max(dp[i-1][j], dp[i][j-1]);
			}
		}
	} 
	cout<<dp[lenA][lenB]<<endl;
	return 0;
 } 

14题 最长回文子串

题目描述

image.png 样例输入

PATZJUJZTACCBCC

样例输出

9

Code

#include<bits/stdc++.h>
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 1010;
char S[N];
//dp[i][j]表示S[i]到S[j]是否为回文串,是为1,否则为0 
int dp[N][N];
int main()
{
	gets(S);
	int len = strlen(S), ans = 1;
	//初始化 
	memset(dp, 0, sizeof(dp));
	//边界条件 
	for(int i = 0; i < len; i++){
		dp[i][i] = 1;
		if(i < len - 1){
			if(S[i] == S[i+1]){
				dp[i][i+1]=1;
				ans=2;
			}
		}
	}
	//状态转移方程
	for(int L = 3; L <= len; L++){//枚举子串的长度 
		for(int i = 0; i + L - 1 < len; i++){//枚举子串的起始端点 
			int j = i + L - 1;//子串的右端点 
			if(S[i] == S[j] && dp[i+1][j-1] == 1){
				dp[i][j]=1;
				ans = L;
			}
		}
	}	
	cout<<ans<<endl;
	return 0;
 } 

14题 等腰三角形

题目描述

给定 n 个坐标,求其中 3 个坐标能表示一个等腰三角形的组数。

三点共线不算三角形,等边三角形为特殊的等腰三角形。

输入描述 `` 第一行一个整数 n(0≤n≤400)

其后 n 行每行两个整数 xi,yi(−500≤xi,yi≤500),保证没有重复坐标。 ``

输入

 4
 1 1
 -1 1
 -1 -1
 1 -1

输出

4

Code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;

int main() {
	int n;
	cin>>n;
	vector <pii> s(n+1);
	for(int i = 1; i <= n; i++) 
	{
		cin>>s[i].first>>s[i].second;
	}
	if(n <= 2) 
	{
		cout<<0<<endl;
		return 0;
	}
	int cnt=0;
	for(int i = 1; i <= n; i++)
	{
		for(int j = i + 1; j <= n; j++)
		{
			for(int k = j + 1; k <= n; k++)
			{
				int x1, y1, x2, y2, x3, y3;
				x1 = s[i].first, y1 = s[i].second;
				x2 = s[j].first, y2 = s[j].second;
				x3 = s[k].first, y3 = s[k].second;
                                //向量积(x1-x3,y1-y3)×(x2-x3,y2-y3)
				int crossProduct = (x1-x3)*(y2-y3) - (x2-x3)*(y1-y3);
                                if(crossProduct == 0)  // 三点共线
                                    continue;
                                int a = (pow(x1-x2, 2) + pow(y1-y2,2));
                                int b = (pow(x1-x3, 2) + pow(y1-y3,2));
                                int c = (pow(x2-x3, 2) + pow(y2-y3,2));
                                if(a==b || a==c || b==c)  // 是等腰三角形
                                    cnt++;
			}
		 } 
	}
	cout<<cnt<<endl;
}

15题 块

题目描述

image.png

Code

BFS实现:

#include<bits/stdc++.h>
using namespace std;
const int maxn=100;
struct node{
	int x,y;
}Node;

int n=7,m=7;
bool inq[maxn][maxn]={false};
int matrix[maxn][maxn]={{0,1,1,1,0,0,1},{0,0,1,0,0,0,0},{0,0,0,0,1,0,0},{0,0,0,1,1,1,0},{1,1,1,0,1,0,0},{1,1,1,1,0,0,0}};
//增量数组
int X[4]={0,0,-1,1};
int Y[4]={1,-1,0,0};
//边界条件
bool judge(int x,int y){
	if(x>=n || x<0 ||y>=m || y<0){
		return false;
	}
	if(matrix[x][y]==0 || inq[x][y]==true){
		return false;
	}
	return true;
}
//BFS访问(x,y)所在的块,将块中所有"1"设置为true
void BFS(int x,int y){
	queue<node> Q;
	Node.x=x;
	Node.y=y;
	Q.push(Node);
	inq[x][y]=true;
	while(!Q.empty()){
		node top=Q.front();
		Q.pop();
		for(int i=0;i<4;i++){
			int newX=top.x+X[i];
			int newY=top.y+Y[i];
			if(judge(newX,newY)){
				Node.x=newX;
				Node.y=newY;
				Q.push(Node);
				inq[newX][newY]=true; 
			}
		}
	}
}

int main(){
	int ans=0;
	for(int i=0;i<n;i++){
		for(int j=0;j<m;j++){
			if(matrix[i][j]==1 && inq[i][j]==false){
				ans++;
				BFS(i,j);
			}
		}
	}
	cout<<ans<<endl;
	return 0;
}

16题 华强劈瓜

问题描述

华强在一个铺着方形地砖的房间中,每块地砖上都放的一个有西瓜。他站在一块放有西瓜的瓷砖上,并且可以上下左右移动到其它瓷砖上,但是前提是瓷砖上得有西瓜,毕竟华强是个爱劈西瓜的人。
请你写一个程序来计算华强能在这个房间里面劈到多少个西瓜。

输入描述
第一行两个整数 n m 代表这个房间里面的瓷砖有n行m列 n和m不超过20
接下来n行,每行包含m个字符,每个字符代表该地砖上是否有瓜,状态如下所示:
'.'有瓜
'#'无瓜
'@'华强的初始位置(只出现一次)

样例输入

9 6
....#.
.....#
......
......
......
......
......
#@...#
.#..#.

样例输出

45

Code

DFS实现:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int dx = 0, dy = 0;
int n, m, res = 1;
char arr[25][25];
int X[4] = {0, 0, 1,-1};
int Y[4] = {1,-1, 0, 0};
struct node {
	int x, y;
};

void dfs(int x, int y)
{	
	queue<node> q;
	node start;
	start.x = x;
	start.y = y;
	q.push(start);
	while (!q.empty()) {
		start = q.front();
		q.pop();
		for (int i = 0; i < 4; i++) {
			int ax = X[i] + start.x;
            int ay = Y[i] + start.y;
			if (ax >= 0 && ax < n && ay >= 0 && ay < m && arr[ax][ay] == '.') {	 
				arr[ax][ay] = '#';
				res++;
				dfs(ax, ay);
			}
	   }
	}
}

int main()
{
	cin >> n >> m;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			cin >> arr[i][j];
			if (arr[i][j] == '@') {
				dx = i; dy = j;
			}
		}
	}
	dfs(dx, dy);
	cout << res << endl;
	return 0;
}

BFS实现:

#include<bits/stdc++.h>
using namespace std;
const int maxn=10010;
struct node{
	int x,y;
}start;

int n, m;
int dx, dy;
char matrix[maxn][maxn];
int inq[maxn][maxn] = {false};
int X[4]={ 0, 0,-1, 1};
int Y[4]={ 1,-1, 0, 0};
int ans=0;
int cnt=0;

bool judge(int x, int y) {
	if(x >= n || x < 0 || y >= m || y < 0) {
		return false;
	}
	if(matrix[x][y] == 0 || inq[x][y] == true) {
		return false;
	}
	if(matrix[x][y] == '#') {
		return false;
	}
	return true;
}

void BFS(int x, int y)
{
	queue<node> Q;
	start.x = x;
	start.y = y;
	Q.push(start);
	inq[x][y] = true;
	while( !Q.empty() ){
		node top = Q.front();
		Q.pop();
		ans++;
		inq[start.x][start.y] = true;
		for(int i = 0; i < 4; i++){
			int newX = top.x + X[i];
			int newY = top.y + Y[i];
			if(judge(newX, newY)) {
				start.x = newX;
				start.y = newY;
				Q.push(start);
				inq[newX][newY] = true; 
			}
		}
	}
 } 
 
int main()
{
	cin >> n >> m;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			cin >> matrix[i][j];
			if (matrix[i][j] == '@') {
				dx = i; 
				dy = j;
				matrix[i][j] = '.';
			}
		}
	}
	BFS(dx, dy);
	cout << ans << endl;
	return 0;
}