挑战程序设计竞赛(课后题难题汇总)

1. AOJ 0033 Ball(贪心)

#include<cstdio>
#include<algorithm>
using namespace std;
int T, a[15];
void solve()
{int x1 = a[0], x2 = -1e8;for(int i = 1; i < 10; i++){if(a[i] > x1 && a[i] > x2){if(a[i] - x1 > a[i] - x2){x2 = a[i];}else{x1 = a[i];}}else if(a[i] > x1){x1 = a[i];}else if(a[i] > x2){x2 = a[i];}else{printf("NO\n");return;}}printf("YES\n");
}
int main()
{scanf("%d", &T);while(T--){for(int i = 0; i < 10; i++){scanf("%d", &a[i]);}solve();}return 0;
}

(1)无需用stack,因为我们只关心最上面的两个数,因此只需用x1, x2保存最上面的两个数即可。
(2)初始化x1应为a[0],x2应初始化为-INF,不能把x2初始化为a[1],应该是直到不能往x1那一摞放小球的时候才往x2放。

2.POJ 3009 Curling 2.0 (回溯法)

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int field[25][25], dx[5] = {1, -1, 0, 0}, dy[5] = {0, 0, 1, -1};
int N, M, res, res0, sx, sy, gx, gy;
void dfs(int x, int y)
{if(res > 10){return;}for(int i = 0; i < 4; i++){int nx = x + dx[i], ny = y + dy[i];bool go = 0;while(1 <= nx && nx <= N && 1 <= ny && ny <= M && field[nx][ny] != 1){go = true;if(nx == gx && ny == gy){res0 = min(res, res0);}nx += dx[i], ny += dy[i];}if(field[nx][ny] == 1 && go){field[nx][ny] = 0;res++;dfs(nx - dx[i], ny - dy[i]);res--;field[nx][ny] = 1;}}}
int main()
{while(scanf("%d%d", &M, &N) && N){memset(field, 0, sizeof(field));res = 1, res0 = 1e8;for(int i = 1; i <= N; i++){for(int j = 1; j <= M; j++){scanf("%d", &field[i][j]);if(field[i][j] == 2){sx = i, sy = j;}else if(field[i][j] == 3){gx = i, gy = j;}}}dfs(sx, sy);if(res0 <= 10){printf("%d\n", res0);}else{printf("%d\n", -1);}}return 0;
}

(1)注意这个数组下标从1开始,否则如果下标从0开始,如果一旦从左边或上边扔出墙外,下标会变为-1,然后会越界。
(2)field每组数据都一定要初始化为0,因为跑到墙外面怎么判断?一个是跳出while循环,另一个是在下面if(field[nx][ny] == 1 && go) 那里,如果不初始化,从右边和下边出了墙后,本来field对应的应该是0,但是却有可能是上一组数据的值,如果原本是1,就又进了if判断,导致出错。

3.AOJ 0558 Cheese

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int INF = 1e8;
int N, M, C, d[1005][1005], dx[] = {1, -1, 0, 0}, dy[] = {0, 0, 1, -1};
typedef pair<int, int> P;
P cheese[15];
char field[1005][1005];
int bfs(int sx, int sy, int gx, int gy)
{for(int i = 0; i < N; i++){fill(d[i], d[i] + M, INF);}d[sx][sy] = 0;queue<P> que;que.push(P(sx, sy));while(!que.empty()){P p = que.front();que.pop();int x = p.first, y = p.second;if(x == gx && y == gy){return d[x][y];}for(int i = 0; i < 4; i++){int nx = x + dx[i], ny = y + dy[i];if(0 <= nx && nx < N && 0 <= ny && ny < M && field[nx][ny] != 'X' && d[nx][ny] == INF){que.push(P(nx, ny));d[nx][ny] = d[x][y] + 1;}}}
}
int main()
{scanf("%d%d%d", &N, &M, &C);for(int i = 0; i < N; i++){scanf("%s", field[i]);}for(int i = 0; i < N; i++){for(int j = 0; j < M; j++){if(field[i][j] == 'S'){cheese[0] = P(i, j);}else if('0' < field[i][j] && field[i][j] <= '9'){cheese[field[i][j] - '0'] = P(i, j);}}}int res = 0;for(int i = 1; i <= C; i++){res += bfs(cheese[i - 1].first, cheese[i - 1].second, cheese[i].first, cheese[i].second);}printf("%d\n", res);return 0;
}

(1)学会把问题划分为子问题。
(1)一定要注意!虽然没有用全局变量。全局变量一定要注意!不要在后面用的时候不要再int声明,不然会屏蔽掉外部变量!
(2)此题奶酪工厂是可以直接经过的,不是没吃过的工厂就就不让过。

4.POJ 3669 Meteor Shower

(1)这次又想了一个方法,设置一个field的二维数组,记录流星砸的最早时间,永远不砸就是INF。然后算人走的时间,用d保存,一旦有field[x][y] <= d[x][y],就把d[x][y]设为2 * INF。最后,遍历两个数组,寻找field[x][y] == INF 的地方对应的d[x][y]的最小值。个人感觉这个方法更简单一些。

#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
const int N = 305, M = 305, maxc = 50005, INF = 1e8;
int C, x[maxc], y[maxc], t[maxc], dx[4] = {0, 0, 1, -1}, dy[4] = {1, -1, 0, 0};
int field[N][M], d[N][M];
typedef pair<int, int> P;
void solve()
{for(int i = 0; i < N; i++){for(int j = 0; j < M; j++){field[i][j] = d[i][j] = INF;}}for(int i = 0; i < C; i++){int x1 = x[i], y1 = y[i];//防止重复砸。注意是找最小值,因为不一定先输入的流星砸得就早。field[x1][y1] = min(field[x1][y1], t[i]);for(int j = 0; j < 4; j++){int nx = x1 + dx[j], ny = y1 + dy[j];if(0 <= nx && nx < N && 0 <= ny && ny < M){field[nx][ny] = min(field[nx][ny], t[i]);}}}d[0][0] = 0;queue<P> que;que.push(P(0, 0));while(!que.empty()){P p = que.front();que.pop();int x = p.first, y = p.second;if(d[x][y] >= field[x][y]){d[x][y] = 2 * INF;//切记,这里别设为INF,不然无法区分不能经过这个地方与还没有到这个地方两种情况。continue;}for(int i = 0; i < 4; i++){int nx = x + dx[i], ny = y + dy[i];if(0 <= nx && nx < N && 0 <= ny && ny < M && d[nx][ny] == INF){que.push(P(nx, ny));d[nx][ny] = d[x][y] + 1;}}}int res = INF;for(int i = 0; i < N; i++){for(int j = 0; j < M; j++){if(field[i][j] == INF){res = min(d[i][j], res);}}}if(res == INF){printf("%d\n", -1);}else{printf("%d\n", res);}
}
int main()
{scanf("%d", &C);for(int i = 0; i < C; i++){scanf("%d%d%d", &x[i], &y[i], &t[i]);}solve();return 0;
}

kuangbin系列

1.HDU 2612 Find a way

(1)这道题遍历两边城市地图就可以了,否则会超时。

#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int INF = 1e7;
int N, M, sx1, sy1, sx2, sy2;
int dx[] = {0, 0, 1, -1}, dy[] = {1, -1, 0, 0};
char field[205][205];
int d[205][205];
typedef pair<int, int> P;
vector<P> kfc;
void bfs(int sx, int sy)
{for(int i = 0; i < N; i++){for(int j = 0; j < M; j++){d[i][j] = INF;}}d[sx][sy] = 0;queue<P> que;que.push(P(sx, sy));while(!que.empty()){P p = que.front();que.pop();int x = p.first, y = p.second;for(int i = 0; i < 4; i++){int nx = x + dx[i], ny = y + dy[i];if(0 <= nx && nx < N && 0 <= ny && ny < M && field[nx][ny] != '#' && d[nx][ny] == INF){que.push(P(nx, ny));d[nx][ny] = d[x][y] + 11;}}}
}
void solve()
{int sz = kfc.size();vector<int> res1, res2;bfs(sx1, sy1);for(int i = 0; i < sz; i++){int x = kfc[i].first, y = kfc[i].second;res1.push_back(d[x][y]);}bfs(sx2, sy2);for(int i = 0; i < sz; i++){int x = kfc[i].first, y = kfc[i].second;res2.push_back(d[x][y]);}int res = 1e9;for(int i = 0; i < sz; i++){res = min(res, res1[i] + res2[i]);}printf("%d\n", res);
}
int main()
{while(scanf("%d%d", &N, &M) == 2){kfc.clear();for(int i = 0; i < N; i++){scanf("%s", &field[i]);}for(int i = 0; i < N; i++){for(int j = 0; j < M; j++){if(field[i][j] == '@'){kfc.push_back(P(i, j));}else if(field[i][j] == 'Y'){sx1 = i, sy1 = j;}else if(field[i][j] == 'M'){sx2 = i, sy2 = j;}}}solve();}return 0;
}

2.UVA 11624 Fire!

(1)这道题很恶,题目只说有一个J,但没说只有一个F,因此有可能有多个火源。
(2)一开始我的思路是先算人到边界时间,再算每个火到边界的最短时间,若人到边界的时间小于火到边界的时间,则可以逃脱。但是这种算法会超时。
(3)因此,只能把这个地图遍历一次,先把所有的火源推入队列,然后把人推入队列,这样表明火先走,人再走。只要火到的地方就变成墙。别忘一开始把火的位置变成墙。

WA,但并不知道是哪里错了。

#include<cstdio>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
const int INF = 1e8;
int T, N, M, dx[] = {1, -1, 0, 0}, dy[] = {0, 0, 1, -1};
int d[1005][1005], sx, sy;
char field[1005][1005];
struct P
{int x, y;bool kind;  //0 indicates John, and 1 indicates the fire;
};
vector<P> fire;
int bfs()
{for(int i = 0; i < N; i++){for(int j = 0; j < M; j++){d[i][j] = INF;}}d[sx][sy] = 0;queue<P> que;int sz = fire.size();for(int i = 0; i < sz; i++){que.push(fire[i]);}que.push({sx, sy, false});while(!que.empty()){P p = que.front();que.pop();int x = p.x, y = p.y;for(int i = 0; i < 4; i++){int nx = x + dx[i], ny = y + dy[i];if(0 <= nx && nx < N && 0 <= ny && ny < M && field[nx][ny] != '#' && d[nx][ny] == INF){if(p.kind){field[nx][ny] = '#';que.push({nx, ny, true});}else{que.push({nx, ny, false});d[nx][ny] = d[x][y] + 1;}}}}int res = INF;for(int i = 0; i < N; i++){res = min(res, d[i][0]);res = min(res, d[i][M - 1]);}for(int j = 0; j < M; j++){res = min(res, d[0][j]);res = min(res, d[N - 1][j]);}return res + 1;
}
void solve()
{for(int i = 0; i < N; i++){for(int j = 0; j < M; j++){if(field[i][j] == 'J'){sx = i, sy = j;}else if(field[i][j] == 'F'){fire.push_back({i, j, true});field[i][j] = '#';}}}int res = bfs();if(res >= INF){printf("IMPOSSIBLE\n");}else{printf("%d\n", res);}
}
int main()
{scanf("%d", &T);while(T--){scanf("%d%d", &N, &M);for(int i = 0; i < N; i++){scanf("%s", field[i]);}solve();}return 0;
}

cf

1.D. Solve The Maze

这道题我的一开始思路是把所有坏人的四个方向判断一下,若有好人,则结束并输出No,否则换成‘#’。然后把所有连成一起的好人换成‘.’(用深搜),这样可以减少搜索数量。最后用广搜看看每个好人到终点的距离是否为INF。

专题一:简单搜索、深搜、广搜相关推荐

  1. 深搜广搜专题【DFS】【BFS】

    深搜广搜专题 又是一年专题时,这次的专题是BFS和DFS,我们刚加入acm时的噩梦,然而现在已经写起来很舒服了(OS:那你还A不出题?) BFS和DFS都是通过对所有的点进行遍历来得到结果的,是一种比 ...

  2. kuangbin 专题一 简单搜索

    kuangbin 专题一 简单搜索 1.POJ1321棋盘问题[DFS] 代码 自己的想法 2.POJ2251Dungeon Master[三维空间BFS] 代码 自己的想法 3.POJ3278 Ca ...

  3. 简单深搜广搜基本模板

    简单搜索 DFS: 剪枝,条件 容易超时,超时后基本就是剪枝的问题/无限递归?,或者用广搜试试? 模板(自己的理解) int n,m;//一般输入的行列数/边界 int mov[4][2] = {1, ...

  4. 小游戏系列算法之五广度优先搜索,双向广搜,八数码,华容道

    前段时间在玩仙五前,遇上了蚩尤冢拼图这个小游戏. 其实就是八数码问题,一直想着如何才能用最少步数求解,于是就写了个程序. Q1:什么是八数码问题? A1:首先假定一个3*3的棋盘(如上图),分别有1, ...

  5. 第七届蓝桥杯-剪邮票(深搜+广搜)

    剪邮票 如下图, 有12张连在一起的12生肖的邮票. 现在你要从中剪下5张来,要求必须是连着的. (仅仅连接一个角不算相连)比如,下面两个图中,粉红色所示部分就是合格的剪取. 请你计算,一共有多少种不 ...

  6. poj3083 Children of the Candy Corn 深搜+广搜

    这道题有深搜和广搜.深搜还有要求,靠左或靠右.下面以靠左为例,可以把简单分为上北,下南,左西,右东四个方向.向东就是横坐标i不变,纵坐标j加1(i与j其实就是下标).其他方向也可以这样确定.通过上一步 ...

  7. 力扣 547. 朋友圈 c语言 三种解法 深搜 广搜 并查集。

    题目: 并查集: /*力扣 547 朋友圈 并查集 c语言 2020/12/14 1:04 by ksks14*/ /*初始化 查找 合并*/ #define maxsize 10000 int fl ...

  8. 【图论专题】BFS中的双向广搜 和 A-star

    双向广搜 AcWing 190. 字串变换 #include <cstring> #include <iostream> #include <algorithm> ...

  9. 搜索:深搜/广搜 获取岛屿数量

    题目描述: 用一个二维数组代表一张地图,这张地图由字符"0"与字符"1"组 成,其中"0"字符代表水域,"1"字符代表小 ...

  10. 最是一年留不住,彩云易散琉璃碎---补题模拟,深搜广搜简单题

    链接:登录-专业IT笔试面试备考平台_牛客网 来源:牛客网 题目a 在风景如画,美女如云的SMU生活学习一年后,多金的花样少年JolerJolerJoler练成了见女生必送鲜花的浪漫绝技.这一天,Jo ...

最新文章

  1. mac软件全屏时候最顶上任务栏保留,MAC能不能做一个把程序放在顶部菜单栏的功能...
  2. 深入理解openstack网络架构(2)----Basic Use Cases
  3. java big o_java – 计算Big-O复杂性
  4. python中mat函数_python matplotlib中的subplot函数使用详解
  5. APACHE2 修改HTTPD.CONF 后启动错误
  6. ecshop静态、 ecshop伪静态、ecshop伪静态设置详细方法、ECSHOP静态化方法
  7. 【TOJ1132】Square Root,二次同余方程
  8. STM8单片机读取DHT11温湿度传感器
  9. 大括弧之战 代码风格
  10. 如何解决代码嵌套太深问题
  11. mysql服务器是否支持tcp/ip连接,(3)MySQL客户端与服务端的TCP/IP及socket连接方式-Go语言中文社区...
  12. python的with用法
  13. 华为认证的考试费用和重认证
  14. 五年级英语测试题软件,小学五年级英语测试题
  15. FFmpeg进阶:给视频添加文字水印
  16. 使用tkinter实现 loading 等待效果
  17. 分享暄桐好作业之《灵飞经》,静观春意生长
  18. java毕业设计物业管理系统源码+lw文档+mybatis+系统+mysql数据库+调试
  19. 智和信通搭建高可靠、真稳定IT运维平台,助力能源行业高效生产
  20. Docker使用docker compose搭建Jellyfin私人媒体服务器 个人电影网站

热门文章

  1. 榕树贷款索引优劣势,索引分类和建索引命令
  2. 润乾集算报表用Java动态修改报表数据源
  3. 基于SM3的HMAC算法的实现
  4. python文字转图片(二值、RGB)以及numpy数组
  5. 出行平台T3出行正式上线
  6. 【Servlet】Servlet 详解(使用+原理)
  7. 华夏幸福创新中心携手入驻企业参展科博会 加速区域经济发展
  8. 定时器和promise_浅析setTimeout与Promise
  9. R语言多因素有交互方差分析(Two-Way ANOVA):检测和理解两个因素之间的交互作用的最简单的方法是使用交互作用图、双因素交互作用图可视化(interaction plot)
  10. 带小孩成都到昆明暑假三日游攻略