1.数塔问题
题目描述
在讲述DP算法的时候,一个经典的例子就是数塔问题,它是这样描述的:
有如下所示的数塔,要求从顶层走到底层,若每一步只能走到相邻的结点,则经过的结点的数字之和最大是多少?

输入格式
输入数据首先包括一个整数C,表示测试实例的个数,每个测试实例的第一行是一个整数N(1 <= N <= 100),表示数塔的高度,接下来用N行数字表示数塔,其中第i行有个i个整数,且所有的整数均在区间[0,99]内。
输出格式
对于每个测试实例,输出可能得到的最大和,每个实例的输出占一行。
样例输入
1 5 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5
样例输出
30
源代码
#include<bits/stdc++.h>
using namespace std;
struct node{
int x,y,value;
}que[10005];
int rear=0,front=0;
int a[105][105];
int lastlevel,maxv;
void bfs(int x,int y){
struct node p,q;
p.x=x;
p.y=y;
p.value=a[x][y];
que[rear++]=p;
while(rear!=front){
q=que[front++];
if(q.x==lastlevel){
if(maxv<q.value) maxv=q.value;
}else{
p.x=q.x+1;
p.y=q.y;
p.value=q.value+a[q.x+1][q.y];
que[rear++]=p;
p.x=q.x+1;
p.y=q.y+1;
p.value=q.value+a[q.x+1][q.y+1];
que[rear++]=p;
}
}
}
int main(){
int n,m;
cin>>n;
while(n--){
cin>>m;
for(int i=0;i<m;i++){
for(int j=0;j<=i;j++)cin>>a[i][j];
}
lastlevel=m-1;
maxv=0;
bfs(0,0);
cout<<maxv<<endl;
}
return 0;
}
2.细胞
题目描述
一矩形阵列由数字0到9组成,数字1到9代表细胞,细胞的定义为沿细胞数字上下左右还是细胞数字则为同一细胞,求给定矩形阵列的细胞个数。如:
阵列
4 10
0234500067
1034560500
2045600671
0000000089
有4个细胞。
输入格式
第一行为矩阵的行n和列m;
下面为一个n×m的矩阵。
输出格式
细胞个数。
样例输入 #1
4 10 0234500067 1034560500 2045600671 0000000089
样例输出 #1
4
源代码
#include<bits/stdc++.h>
using namespace std;
int dx[4]={-1, 0, 1, 0}, dy[4]={0, 1, 0, -1};
int cell[100][100], num=0, n, m;
void bfs(int x,int y)
{ int new_x, new_y, i;
int queue[1000][3], head=0, tail=0;
cell[x][y]=0;
queue[tail][1]=x; queue[tail][2]=y; tail++;
while(head<tail)
{ x = queue[head][1]; y = queue[head][2];
head++;
for (i=0;i<=3;i++)
{ new_x = x+dx[i]; new_y = y+dy[i];
if ((new_x>=0)&&(new_x<m)&&(new_y>=0)&&(new_y<n)&&(cell[new_x][new_y]))
{ queue[tail][1]=new_x;
queue[tail][2]=new_y;
tail++ ;
cell[new_x][new_y]=0;
}
}
}
}
int main()
{
int i,j;
char s[100],ch;
scanf("%d%d\n",&m,&n);
for (i=0;i<m;i++)
{ gets(s);
for (j=0; j<n; j++) cell[i][j]=s[j]-'0';
}
for (i=0; i<m; i++)
for (j=0; j<n; j++)
if (cell[i][j])
{
num++;
bfs(i, j);
}
printf("%d\n",num);
return 0;
}
3.最小步数
题目描述
在各种棋中,棋子的走法总是一定的,如中国象棋中马走“日”。有一位小学生就想如果马能有两种走法将增加其趣味性,因此,他规定马既能按“日”走,也能如象一样走“田”字。他的同桌平时喜欢下围棋,知道这件事后觉得很有趣,就想试一试,在一个(100×100)的围棋盘上任选两点A、B,A点放上黑子,B点放上白子,代表两匹马。棋子可以按“日”字走,也可以按“田”字走,俩人一个走黑马,一个走白马。谁用最少的步数走到左上角坐标为(1,1)的点时,谁获胜。现在他请你帮忙,给你A、B两点的坐标,想知道两个位置到(1,1)点可能的最少步数。
输入格式
A、B两点的坐标。
输出格式
最少步数。
样例输入 #1
12 16 18 10
样例输出 #1
8
9
源代码
#include<bits/stdc++.h>
using namespace std;
int dx[12]={-2,-2,-1,1,2,2,2,2,1,-1,-2,-2};
int dy[12]={-1,-2,-2,-2,-2,-1,1,2,2,2,2,1};
int main(){
int s[101][101],x1,y1,x2,y2,steps;
int x,y,new_x,new_y;
int que[10000][4]={0},head=0,tail=0;
cin>>x1>>y1>>x2>>y2;
memset(s,0xff,sizeof(s));
que[tail][1]=1;
que[tail][2]=1;
que[tail][3]=0;
tail++;
while(head<tail){
x=que[head][1];
y=que[head][2];
steps=que[head][3];
head++;
for(int d=0;d<=11;d++){
new_x=x+dx[d];
new_y=y+dy[d];
if(new_x>0&&new_x<=100&&new_y>0&new_y<=100){
if(s[new_x][new_y]==-1){
que[tail][1]=new_x;
que[tail][2]=new_y;
que[tail][3]=steps+1;
tail++;
s[new_x][new_y]=steps+1;
if(s[x1][y1]>0&&s[x2][y2]>0){
cout<<s[x1][y1]<<endl;
cout<<s[x2][y2]<<endl;
return 0;
}
}
}
}
}
}
4.迷宫
题目描述
小 C 最近在研究机器人,他想看看自己的机器人够不够智能,于是他将机器人放在一个 n×mn×m 的迷宫中,看看机器人能不能在最短的时间内到达目的地,可是小 C 不知道最短的时间是多少,现在请你帮他算算机器人到达目的地的最短时间是多少?
输入格式
输入数据第一行两个整数 n,m (1≤n,m≤420)n,m (1≤n,m≤420)。
接下来 nn 行,每行 mm 个元素,表示迷宫的每个方格。
S表示机器人的出发点,T表示目的地,#表示该方格不能通过,.表示可以通过。
输出格式
输出一个整数表示机器人到达目的地的最短时间。
如果机器人不能到达目的地,输出 -1。
样例输入 #1
3 3 S.. ##. .T.
样例输出 #1
5
源代码
#include<bits/stdc++.h>
using namespace std;
int n,m;
int dir[2][4]={{1,-1,0,0},{0,0,1,-1}};
int dis[510][510];
char mp[510][510];
queue<pair<int,int> >q;
void bfs(int i,int j)
{
q.push({i,j});
while(!q.empty()){
int x,y;
x = q.front().first; y = q.front().second;
q.pop();
for(int i=0; i<4; ++i){
int xx=x+dir[0][i], yy=y+dir[1][i];
if(0<=xx&&xx<n&&0<=yy&&yy<m&&dis[xx][yy]==-1){
if(mp[xx][yy]=='.'){
dis[xx][yy]=dis[x][y]+1;
q.push( {xx,yy} );
}
else if(mp[xx][yy]=='T'){
cout<<dis[x][y]+1<<'\n';
return;
}
}
}
}
cout<<"-1\n";
}
int main()
{
memset(dis,-1,sizeof dis);
cin>>n>>m;
for(int i=0;i<n;++i)
cin>>mp[i];
for(int i=0;i<n;++i)
for(int j=0;j<m;++j)
{
if(mp[i][j]=='S')
{
dis[i][j]=0; bfs(i,j);
}
}
return 0;
}
5.走迷宫
题目描述
一个迷宫由R行C列格子组成,有的格子里有障碍物,不能走;有的格子是空地,可以走。
给定一个迷宫,求从左上角走到右下角最少需要走多少步(数据保证一定能走到)。只能在水平方向或垂直方向走,不能斜着走。
输入格式
第一行是两个整数,R和C,代表迷宫的长和宽。( 1≤ R,C ≤ 40)
接下来是R行,每行C个字符,代表整个迷宫。
空地格子用‘.’表示,有障碍物的格子用‘#’表示。
迷宫左上角和右下角都是‘.’。
输出格式
输出从左上角走到右下角至少要经过多少步(即至少要经过多少个空地格子)。计算步数要包括起点和终点。
样例输入 #1
5 5 ..### #.... #.#.# #.#.# #.#..
样例输出 #1
9
源代码
#include<bits/stdc++.h>
using namespace std;
int minSteps(const vector<string>& maze, pair<int, int> start, pair<int, int> end) {
vector<pair<int, int> > directions;
directions.push_back(make_pair(-1, 0));
directions.push_back(make_pair(1, 0));
directions.push_back(make_pair(0, -1));
directions.push_back(make_pair(0, 1));
queue<pair<int, int> > q;
map<pair<int, int>, int> steps;
q.push(start);
steps[start] = 1;
while (!q.empty()) {
pair<int, int> current = q.front();
q.pop();
if (current == end) {
return steps[end];
}
for (int i = 0; i < directions.size(); ++i) {
int nx = current.first + directions[i].first;
int ny = current.second + directions[i].second;
if (nx >= 0 && nx < maze.size() && ny >= 0 && ny < maze[0].size() && maze[nx][ny] == '.' && !steps.count(make_pair(nx, ny))) {
q.push(make_pair(nx, ny));
steps[make_pair(nx, ny)] = steps[current] + 1;
}
}
}
return -1;
}
int main() {
int R, C;
cin >> R >> C;
vector<string> maze(R);
for (int i = 0; i < R; ++i) {
cin >> maze[i];
}
pair<int, int> start = make_pair(0, 0);
pair<int, int> end = make_pair(R - 1, C - 1);
int result = minSteps(maze, start, end);
cout << result << endl;
return 0;
}
6.抓住那头牛
题目描述
农夫知道一头牛的位置,想要抓住它。农夫和牛都位于数轴上,农夫起始位于点N(0≤N≤100000),牛位于点K(0≤K≤100000)。农夫有两种移动方式:
1、从X移动到X-1或X+1,每次移动花费一分钟
2、从X移动到2*X,每次移动花费一分钟
假设牛没有意识到农夫的行动,站在原地不动。农夫最少要花多少时间才能抓住牛?
输入格式
两个整数,N和K。
输出格式
一个整数,农夫抓到牛所要花费的最小分钟数。
样例输入 #1
5 17
样例输出 #1
4
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
queue<int>que;
int cow[100005];//用于标记是否走过了,并标记走到目前这里花了多少步
int step[3];//三种走法
int n,k;
void bfs()
{
que.push(n);//农夫进队
memset(cow,-1,sizeof(cow));
cow[n]=0;
while(!que.empty())
{
int cur=que.front();
que.pop();
if(cur==k)break;//已经抓到牛了
//三种移动方式
step[0]=cur-1;
step[1]=cur+1;
step[2]=cur*2;
for(int i=0;i<3;i++)
{
if(step[i]>=0&&step[i]<100001&&cow[step[i]]==-1)
{
que.push(step[i]);
cow[step[i]]=cow[cur]+1;//进行标记
}
}
}
cout<<cow[k]<<endl;
}
int main()
{
cin>>n>>k;
bfs();
return 0;
}


被折叠的 条评论
为什么被折叠?



