当前位置:   article > 正文

ACwing算法备战蓝桥杯——刷题_acwing刷题

acwing刷题

BFS:

全球变暖:

  1. 你有一张某海域 N×N 像素的照片,”.”表示海洋、”#”表示陆地,如下所示:
  2. .......
  3. .##....
  4. .##....
  5. ....##.
  6. ..####.
  7. ...###.
  8. .......
  9. 其中”上下左右”四个方向上连在一起的一片陆地组成一座岛屿,例如上图就有 2 座岛屿。
  10. 由于全球变暖导致了海面上升,科学家预测未来几十年,岛屿边缘一个像素的范围会被海水淹没。
  11. 具体来说如果一块陆地像素与海洋相邻(上下左右四个相邻像素中有海洋),它就会被淹没。
  12. 例如上图中的海域未来会变成如下样子:
  13. .......
  14. .......
  15. .......
  16. .......
  17. ....#..
  18. .......
  19. .......
  20. 请你计算:依照科学家的预测,照片中有多少岛屿会被完全淹没。
  21. 输入格式
  22. 第一行包含一个整数N。
  23. 以下 N 行 N 列,包含一个由字符”#”和”.”构成的 N×N 字符矩阵,代表一张海域照片,”#”表示陆地,”.”表示海洋。
  24. 照片保证第 1 行、第 1 列、第 N 行、第 N 列的像素都是海洋。
  25. 输出格式
  26. 一个整数表示答案。
  27. 数据范围
  28. 1≤N≤1000
  29. 输入样例1
  30. 7
  31. .......
  32. .##....
  33. .##....
  34. ....##.
  35. ..####.
  36. ...###.
  37. .......
  38. 输出样例1
  39. 1
  40. 输入样例2
  41. 9
  42. .........
  43. .##.##...
  44. .#####...
  45. .##.##...
  46. .........
  47. .##.#....
  48. .#.###...
  49. .#..#....
  50. .........
  51. 输出样例2
  52. 1
  53. 代码:
  54. #include <iostream>
  55. #include <string>
  56. #include <queue>
  57. #define x first
  58. #define y second
  59. using namespace std;
  60. typedef pair<int,int> PII;
  61. const int N=1010;
  62. int n;
  63. char c[N][N];
  64. bool st[N][N];//判断该岛屿是否遍历过
  65. queue<PII> q;//队列
  66. bool flage=true;//flage表示是否会当前陆地是否会沉没
  67. int dx[4]={1,-1,0,0},dy[4]={0,0,-1,1};
  68. bool check(int i,int j){
  69. bool F=true;
  70. for(int k=0;k<4;k++){
  71. if(c[i+dx[k]][j+dy[k]]=='.') F=false;
  72. }
  73. return F;
  74. }
  75. void bfs(int i,int j){
  76. //初始化
  77. PII start={i,j};
  78. q.push(start);
  79. bool judge=false;//是否有四个方向都是'#'的点;
  80. //遍历
  81. while(q.size()){
  82. PII t=q.front();
  83. q.pop();
  84. if(!judge) judge=check(t.x,t.y);
  85. st[t.x][t.y]=true;
  86. for(int k=0;k<4;k++){
  87. int x1=t.x+dx[k],y1=t.y+dy[k];
  88. if(x1<n-1&&x1>0&&y1<n-1&&y1>0&&!st[x1][y1]&&c[x1][y1]=='#'){//如果下一位置合法
  89. st[x1][y1]=true;
  90. PII temp={x1,y1};
  91. q.push(temp);
  92. }
  93. }
  94. }
  95. if(judge) flage=false;
  96. }
  97. int main(){
  98. cin>>n;
  99. for(int i=0;i<n;i++){
  100. scanf("%s",c[i]);
  101. }
  102. int res=0;
  103. for(int i=1;i<n-1;i++){
  104. for(int j=1;j<n-1;j++){
  105. if(!st[i][j]&&c[i][j]=='#'){//如果发现新岛屿,开始搜索,n大于等于3时才会有岛屿出现
  106. flage=true;//对于每个岛屿重置flage,是否会沉没
  107. bfs(i,j);
  108. if(flage) res+=1;
  109. }
  110. }
  111. }
  112. cout<<res<<endl;
  113. return 0;
  114. }

DFS:

数字替换:

  1. 给定两个整数 n,x。
  2. 你可以对 x 进行任意次以下操作:
  3. 选择 x 的一位数字 y,将 x 替换为 x×y。
  4. 请你计算通过使用上述操作,将 x 变为一个 n 位数字(不含前导 0),所需要的最少操作次数。
  5. 例如,当 n=3,x=2 时,对 2 进行如下 4 次操作,即可使其变为 3 位数字:
  6. 2 替换为 2×2=4
  7. 4 替换为 4×4=16
  8. 16 替换为 16×6=96
  9. 96 替换为 96×9=864
  10. 输入格式
  11. 共一行,包含两个整数 n,x。
  12. 输出格式
  13. 一个整数,表示将 x 变为一个 n 位数字,所需要的最少操作次数。
  14. 如果无解,则输出 -1
  15. 数据范围
  16. 所有测试点满足 2≤n≤191≤x<10n−1
  17. 输入样例1
  18. 2 1
  19. 输出样例1
  20. -1
  21. 输入样例2
  22. 3 2
  23. 输出样例2
  24. 4
  25. 输入样例3
  26. 13 42
  27. 输出样例3
  28. 12
  29. 朴素DFS:
  30. #include <iostream>
  31. #include <algorithm>
  32. #include <cstring>
  33. using namespace std;
  34. typedef long long LL;
  35. int anws=100;
  36. int n;
  37. void dfs(LL x,int c){
  38. int cnt=0;
  39. LL t=x;
  40. bool st[10];
  41. memset(st,0,sizeof st);
  42. while(t){
  43. st[t%10]=true;
  44. cnt++;
  45. t/=10;
  46. }
  47. if(cnt==n){
  48. anws=min(anws,c);
  49. return;
  50. }
  51. for(int i=2;i<=9;i++){
  52. if(!st[i]) continue;
  53. dfs(x*i,c+1);
  54. }
  55. }
  56. int main(){
  57. LL x;
  58. cin>>n>>x;
  59. dfs(x,0);
  60. if(anws==100) cout<<-1<<endl;
  61. else cout<<anws<<endl;
  62. return 0;
  63. }
  64. 剪枝DFS:
  65. #include <iostream>
  66. #include <algorithm>
  67. #include <cstring>
  68. using namespace std;
  69. typedef long long LL;
  70. int anws=100;
  71. int n;
  72. void dfs(LL x,int c){
  73. if(c>=anws) return;
  74. int cnt=0;
  75. LL t=x;
  76. bool st[10];
  77. memset(st,0,sizeof st);
  78. while(t){
  79. st[t%10]=true;
  80. cnt++;
  81. t/=10;
  82. }
  83. if(c+n-cnt>=anws) return;
  84. if(cnt==n){
  85. anws=min(anws,c);
  86. return;
  87. }
  88. for(int i=9;i>=2;i--){
  89. if(!st[i]) continue;
  90. dfs(x*i,c+1);
  91. }
  92. }
  93. int main(){
  94. LL x;
  95. cin>>n>>x;
  96. dfs(x,0);
  97. if(anws==100) cout<<-1<<endl;
  98. else cout<<anws<<endl;
  99. return 0;
  100. }

小猫爬山

  1. 翰翰和达达饲养了 N 只小猫,这天,小猫们要去爬山。
  2. 经历了千辛万苦,小猫们终于爬上了山顶,但是疲倦的它们再也不想徒步走下山了(呜咕>_<)。
  3. 翰翰和达达只好花钱让它们坐索道下山。
  4. 索道上的缆车最大承重量为 W,而 N 只小猫的重量分别是 C1、C2……CN。
  5. 当然,每辆缆车上的小猫的重量之和不能超过 W。
  6. 每租用一辆缆车,翰翰和达达就要付 1 美元,所以他们想知道,最少需要付多少美元才能把这 N 只小猫都运送下山?
  7. 输入格式
  8. 1 行:包含两个用空格隔开的整数,N 和 W。
  9. 2..N+1 行:每行一个整数,其中第 i+1 行的整数表示第 i 只小猫的重量 Ci。
  10. 输出格式
  11. 输出一个整数,表示最少需要多少美元,也就是最少需要多少辆缆车。
  12. 数据范围
  13. 1≤N≤18,
  14. 1≤Ci≤W≤108
  15. 输入样例:
  16. 5 1996
  17. 1
  18. 2
  19. 1994
  20. 12
  21. 29
  22. 输出样例:
  23. 2
  24. 代码:a
  25. #include <iostream>
  26. #include <algorithm>
  27. using namespace std;
  28. const int N=20;
  29. int anws=19;
  30. int n,m;
  31. int w[N];
  32. int sum[N];
  33. void dfs(int u,int cnt){
  34. if(cnt>=anws) return;//最优性剪枝
  35. if(u==n){
  36. anws=cnt;
  37. return;
  38. }
  39. //不增加新车
  40. for(int i=0;i<cnt;i++)
  41. if(sum[i]+w[u]<=m){//可行性剪枝
  42. sum[i]+=w[u];
  43. dfs(u+1,cnt);
  44. sum[i]-=w[u];//记得恢复现场
  45. }
  46. //增租新车
  47. sum[cnt]=w[u];
  48. dfs(u+1,cnt+1);
  49. sum[cnt]=0;//恢复现场
  50. }
  51. int main(){
  52. cin>>n>>m;
  53. for(int i=0;i<n;i++) cin>>w[i];
  54. //搜索顺序剪枝
  55. sort(w,w+n);
  56. reverse(w,w+n);
  57. dfs(0,0);
  58. cout<<anws<<endl;
  59. return 0;
  60. }

带分数

  1. 100 可以表示为带分数的形式:100=3+69258714
  2. 还可以表示为:100=82+3546197
  3. 注意特征:带分数中,数字 19 分别出现且只出现一次(不包含 0)。
  4. 类似这样的带分数,10011 种表示法。
  5. 输入格式
  6. 一个正整数。
  7. 输出格式
  8. 输出输入数字用数码 19 不重复不遗漏地组成带分数表示的全部种数。
  9. 数据范围
  10. 1≤N<106
  11. 输入样例1
  12. 100
  13. 输出样例1
  14. 11
  15. 输入样例2
  16. 105
  17. 输出样例2
  18. 6
  19. 代码:
  20. #include <iostream>
  21. using namespace std;
  22. const int N=15;
  23. int x,res;
  24. int s[N];
  25. bool st[N];
  26. int Tran(int i,int j){//数组转换成数字
  27. int sum=0;
  28. while(i<=j){
  29. sum=sum*10+s[i++];
  30. }
  31. return sum;
  32. }
  33. void find(){//判断是否有满足条件的取法
  34. for(int i=0;i<7;i++){
  35. for(int j=8;j>i+1;j--){
  36. int a=Tran(0,i);
  37. int b=Tran(i+1,j-1);
  38. int c=Tran(j,8);
  39. if(c*x==c*a+b) res++;
  40. }
  41. }
  42. }
  43. void dfs(int c){//求全排列
  44. if(c==9){
  45. find();
  46. return;
  47. }
  48. for(int i=1;i<=9;i++){
  49. if(st[i]) continue;
  50. st[i]=true;
  51. s[c]=i;
  52. dfs(c+1);
  53. st[i]=false;
  54. }
  55. }
  56. int main(){
  57. cin>>x;
  58. dfs(0);
  59. cout<<res<<endl;
  60. return 0;
  61. }

拓扑排序:

  1. 给定一个由 n 个点和 m 条边构成的图。
  2. 不保证给定的图是连通的。
  3. 图中的一部分边的方向已经确定,你不能改变它们的方向。
  4. 剩下的边还未确定方向,你需要为每一条还未确定方向的边指定方向。
  5. 你需要保证在确定所有边的方向后,生成的图是一个有向无环图(即所有边都是有向的且没有有向环的图)。
  6. 输入格式
  7. 第一行包含整数 T,表示共有 T 组测试数据。
  8. 每组数据第一行包含两个整数 n,m。
  9. 接下来 m 行,每行包含三个整数 t,x,y,用来描述一条边的信息,其中 t 表示边的状态,如果 t=0,则表示边是无向边,如果 t=1,则表示边是有向边。x,y 表示这条边连接的两个端点,如果是有向边则边的方向是从 x 指向 y。
  10. 保证图中没有重边(给定了 (x,y),就不会再次出现 (x,y) 或出现 (y,x))和自环(不会出现 x=y 的情况)。
  11. 输出格式
  12. 对于每组数据,如果无法构造出有向无环图,则输出一行 NO。
  13. 否则,先输出一行 YES,随后 m 行,每行包含两个整数 x,y,用来描述最终构造成的有向无环图中的每条边的具体方向(x 指向 y),边的先后顺序随意。
  14. 注意,已经确定方向的边,不能更改方向。
  15. 如果答案不唯一,输出任意合理方案均可。
  16. 数据范围
  17. 对于前三个测试点,1≤n,m≤10
  18. 对于全部测试点,1≤T≤200002≤n≤2×1051≤m≤min(2×105,n(n−1)2),0≤t≤11≤x,y≤n。
  19. 保证在一个测试点中,所有 n 的和不超过 2×105,所有 m 的和不超过 2×105
  20. 输入样例:
  21. 4
  22. 3 1
  23. 0 1 3
  24. 5 5
  25. 0 2 1
  26. 1 1 5
  27. 1 5 4
  28. 0 5 2
  29. 1 3 5
  30. 4 5
  31. 1 1 2
  32. 0 4 3
  33. 1 3 1
  34. 0 2 3
  35. 1 2 4
  36. 4 5
  37. 1 4 1
  38. 1 1 3
  39. 0 1 2
  40. 1 2 4
  41. 1 3 2
  42. 输出样例:
  43. YES
  44. 3 1
  45. YES
  46. 2 1
  47. 1 5
  48. 5 4
  49. 2 5
  50. 3 5
  51. YES
  52. 1 2
  53. 3 4
  54. 3 1
  55. 3 2
  56. 2 4
  57. NO
  58. 代码及部分题解:
  59. #include <iostream>
  60. #include <vector>
  61. #include <cstring>
  62. #define a first
  63. #define b second
  64. using namespace std;
  65. typedef pair<int,int> PII;
  66. const int N=2e5+10;
  67. int n,m;
  68. int h[N],e[N],ne[N],idex;//邻接表
  69. int q[N],d[N];
  70. int st[N];//存储在拓扑队列里的位置
  71. void add(int a,int b){//有向边的加入
  72. ne[idex]=h[a],e[idex]=b,h[a]=idex++;
  73. d[b]++;
  74. }
  75. bool tuopusort(){//拓扑排序
  76. int l=0,r=-1;//模拟队列
  77. for(int i=1;i<=n;i++){
  78. if(!d[i]){
  79. q[++r]=i;
  80. st[i]=r;
  81. }
  82. }
  83. while(l<=r){
  84. int t=q[l++];
  85. for(int j=h[t];j!=-1;j=ne[j]){
  86. d[e[j]]--;
  87. if(!d[e[j]]){
  88. q[++r]=e[j];
  89. st[e[j]]=r;
  90. }
  91. }
  92. return l==n;//包括了无向边的点
  93. }
  94. }
  95. int main(){
  96. int T;
  97. cin>>T;
  98. while(T--){
  99. //主体
  100. //初始化
  101. vector<PII> O;
  102. memset(h,-1,sizeof h);
  103. memset(d,0,sizeof d);
  104. idex=0;
  105. scanf("%d%d",&n,&m);
  106. //输入数据
  107. while(m--){
  108. int t;
  109. int x,y;
  110. scanf("%d%d%d",&t,&x,&y);
  111. if(!t){
  112. PII temp;
  113. temp.a=x;
  114. temp.b=y;
  115. O.push_back(temp);
  116. continue;
  117. }
  118. add(x,y);
  119. }
  120. bool res=tuopusort();//拓扑排序
  121. //拓扑和连通没有关系,所以不加入无向边造成的不连通不会影响拓扑
  122. if(!res) puts("NO");//不存在拓扑序
  123. else{//存在拓扑序
  124. puts("YES");
  125. for(int i=1;i<=n;i++)
  126. for(int j=h[i];j!=-1;j=ne[j])
  127. printf("%d %d\n",i,e[j]);
  128. for(int i=0;i<n;i++) st[q[i]]=i;
  129. for(auto c:O){
  130. if(st[c.a]<st[c.b]) printf("%d %d\n",c.a,c.b);
  131. else printf("%d %d\n",c.b,c.a);
  132. }
  133. }
  134. }
  135. return 0;
  136. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/433965
推荐阅读
  

闽ICP备14008679号