1.队列
编程计算由“*”号围成的下列图形的面积。面积计算方法是统计*号所围成的闭合曲线
中水平线和垂直线交点的数目。
这道题很水,甚至可以不用搜索,直接循环两次就行
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch == '-') f=-1 ; ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-48 ; ch=getchar();}
return x*f;
}
int a[20][20];
int ans;
int main(){
for(register int i(1) ; i<=10 ; i=-~i){
for(register int j(1) ; j<=10 ; j=-~j){
cin >> a[i][j];
}
}
for(register int i(0) ; i<=11 ; i=-~i) a[i][0] = a[0][i] = a[11][i] = a[i][11] = 2;
for(register int i(1) ; i<=10 ; i=-~i){
for(register int j(1) ; j<=10 ; j=-~j){
if(a[i][j]!=1 && (a[i][j-1] == 2 || a[i-1][j] == 2)) a[i][j] = 2;
}
}
for(register int i(10) ; i>=1 ; i--){
for(register int j(10) ; j>=1 ; j--){
if(a[i][j] != 1 && (a[i+1][j] == 2 || a[i][j+1]== 2)) a[i][j] = 2;
}
}
for(register int i(1) ; i<=10 ; i=-~i){
for(register int j(1) ; j<=10 ; j=-~j){
if(a[i][j]== 0) ans++;
}
}
printf("%d",ans);
return 0;
}
2.奇怪的电梯
大楼的每一层楼都可以停电梯,而且第 i 层楼(1<=i<=N)上有一个数字 Ki(0<=Ki<=N)。
电梯只有四个按钮:开,关,上,下。上下的层数等于当前楼层上的那个数字。当然,如果
不能满足要求,相应的按钮就会失灵。例如:3 3 1 2 5 代表了 Ki(K1=3,K2=3,......),从一
楼开始。在一楼,按“上”可以到 4 楼,按“下”是不起作用的,因为没有-2 楼。那么,
从 A 楼到 B 楼至少要按几次按钮呢?
一道广搜的经典题,存两个状态,上和下,接着搜就行
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch == '-') f=-1 ; ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-48 ; ch=getchar();}
return x*f;
}
int n,a,b;
int e[10010],vis[10010];
queue<int>f;
queue<int>s;
int main(){
n=read();a=read();b=read();
for(int i=1 ; i<=n ; i++) e[i] = read();
memset(vis,0,sizeof(vis));
f.push(a);s.push(0);
vis[a] = 1;
while(!f.empty()){
if(f.front() == b){
cout << s.front();
return 0;
}
int x = f.front() + e[f.front()];
if(x<=n && vis[x] == 0){
vis[x] = 1;
f.push(x);
s.push(s.front() + 1);
}
x = f.front() - e[f.front()];
if(x>=1 && vis[x] == 0){
vis[x] = 1;
f.push(x);
s.push(s.front() + 1);
}
f.pop();
s.pop();
}
cout << -1;
return 0;
}
3.产生数
给出一个整数 n(n<=2000)和 k 个变换规则(k≤15)。规则:
① 1 个数字可以变换成另 1 个数字;
② 规则中,右边的数字不能为零。
例如:n=234,k=2 规则为
2 → 5
3 → 6
上面的整数 234 经过变换后可能产生出的整数为(包括原数)234,534,264,564 共 4
种不同的产生数。
求经过任意次的变换(0 次或多次),能产生出多少个不同的整数。仅要求输出不同整
数个数。
这道题比洛谷上的简单,数据范围调小了, 考虑这个数的每一位,如果能变换的话答案加一,记录下来,一直往下找,知道队列为空
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch == '-') f=-1 ; ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-48 ; ch=getchar();}
return x*f;
}
int n,k;
queue<int>q;
int cnt;
int x[20010],y[20010];
int vis[20010];
void bfs(){
q.push(n);
vis[n] = 1;
while(!q.empty()){
int a = q.front();
int z = a,sum = 1;
q.pop();
while(a>0){
int b = a%10;
a /= 10;
for(register int i(1) ; i<=k ; i=-~i){
if(b== x[i]){
int jilu = z - x[i]*sum + y[i]*sum;
if(!vis[jilu]){
vis[jilu] = 1;
q.push(jilu);
cnt++;
}
}
}
sum *= 10;
}
}
}
int main(){
scanf("%d%d",&n,&k);
for(register int i(1) ; i<=k ; i=-~i)scanf("%d%d",&x[i],&y[i]);
bfs();
printf("%d",cnt+1);
return 0;
}
4.家庭问题
有 n 个人,编号为 1,2,......n,另外还知道存在 K 个关系。一个关系的表达为二元组(α,
β)形式,表示α,β为同一家庭的成员。
当 n,k 和 k 个关系给出之后,求出其中共有多少个家庭、最大的家庭中有多少人?
例如:n=6,k=3,三个关系为(1,2),(1,3),(4,5)
此时,6 个人组成三个家庭,即:{1,2,3}为一个家庭,{4,5}为一个家庭,{6}单独为
一个家庭,第一个家庭的人数为最多。
第一眼看上去肯定是一个并查集的题,于是我先拿并查集交了一遍,AC了
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch == '-') f=-1 ; ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-48 ; ch=getchar();}
return x*f;
}
int n,k;
int f[110];
int ans[110];
int cnt;
int maxn = -1e9;
int find(int x){
if(f[x] == x) return x;
return f[x] = find(f[x]);
}
int main(){
cin >> n >> k;
for(register int i(1) ; i<=n ; i=-~i) f[i] = i;
for(register int i(1) ; i<=k ; i=-~i){
int x,y;
cin >> x >> y;
f[find(x)] = find(y);
}
for(register int i(1) ; i<=n ; i=-~i){
if(ans[f[find(i)]] == 0) ans[f[find(i)]]++,cnt++;
else ans[f[find(i)]]++;
}
for(register int i(1) ; i<=n ; i=-~i) maxn = max(maxn,ans[i]);
printf("%d %d",cnt,maxn);
return 0;
}
但比赛的题目是队列,这么做。。(毕竟不太好),所以我就用队列广搜做了一遍
首先是存,用链式前向星存,注意是无向边,然后一个个枚举该点能走到的点,如果这个点未被走到,答案加一,并且用maxn记录家庭的最大数
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch == '-') f=-1 ; ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-48 ; ch=getchar();}
return x*f;
}
int n,k;
int cnt;
int ans1,ans2,maxn;
struct egde{
int to,net;
}e[100010];
int head[100010];
bool vis[100010];
void add(int u,int v){
e[++cnt].to = v;
e[cnt].net = head[u];
head[u] = cnt;
}
void bfs(int x){
if(vis[x]) return;
queue<int>q;
vis[x] = 1;
ans1++;
ans2 = 1;
q.push(x);
while(!q.empty()){
int k = q.front();
q.pop();
for(register int i=head[k] ; i ; i=e[i].net){
if(!vis[e[i].to]){
vis[e[i].to] = 1;
q.push(e[i].to);
ans2++;
}
}
}
maxn = max(maxn,ans2);
}
int main(){
n=read();k=read();
for(register int i(1) ; i<=k ; i=-~i){
int x,y;
x=read();y=read();
add(x,y);
add(y,x);
}
for(register int i(1) ; i<=n ; i=-~i) bfs(i);
printf("%d %d",ans1,maxn);
return 0;
}