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;
}