递归+DFS(入门) [Cloned]
专题链接:https://vjudge.net/contest/343391#overview
A - 超级楼梯
原题链接:https://vjudge.net/problem/27332/origin
完整代码:
#include<stdio.h>
int f(int n)
{
int m[45]={0,1,1};
int i;
for(i=3;i<=n;i++)
{
m[i]=m[i-1]+m[i-2];
}
return m[n];
}
int main()
{
int T,x;
scanf("%d",&T);
while(T--)
{
scanf("%d",&x);
printf("%d\n",f(x));
}
return 0;
}
B - 汉诺塔问题(Hanoi)
原题链接:http://bailian.openjudge.cn/practice/4147?lang=en_US
https://vjudge.net/problem/OpenJ_Bailian-4147
完整代码:
#include<stdio.h>
void hanoi(int n,char A,char B,char C)
{
if(n==1){
printf("%d:%c->%c\n",n,A,C);
}
else{
hanoi(n-1,A,C,B);
printf("%d:%c->%c\n",n,A,C);
hanoi(n-1,B,A,C);
}
}
int main()
{
int n;
char a,b,c;
scanf("%d",&n);
getchar();
scanf("%c %c %c",&a,&b,&c);
hanoi(n,a,b,c);
return 0;
}
C - Prime Ring Problem
原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1016
完整代码:
#include<stdio.h>
#include<math.h>
bool b[1010]; //定义一个数组用来存是否为素数,因为bool只有0和1所以定义bool,当然int型也可以
int ii;
int total;
int a[101];
//判断函数
//pd就是判断的意思,定位bool型和数组b的原因一样
bool pd(int x,int y) //判断是否为素数
{
int k,e;
e=x+y; //用e表示两个数相加,因为是两个数相加判断是否为素数
for(k=2;k<=sqrt(e);k++)
{
if(e%k==0)
{
return 0; //表示不是素数
}
}
return 1; //没有一个数可以整除,表示为素数,返回1
}
//打印函数
int print()
{
total++;
for(int j=1;j<=ii;j++)
{
if(a[1]==1&&j!=ii)
{
printf("%d ",a[j]); //每个数要用空格隔开,但最后一个数直接换行,用一个if判断就行了。
} //如果不这样会格式错误
else if(a[1]==1&&j==ii)
{
printf("%d",a[j]);
}
else return 0; //不retur会打印空行
}
printf("\n");
//return 0;
//因为定义的是int,所以要有返回值,但是对答案不影响,不打retur 0,答案不会错所以我注释掉了。
}
//递归
int search(int t)
{
for(int i=1;i<=ii;i++)
{
if(pd(a[t-1],i)&&(!b[i]))
{
a[t]=i;
b[i]=1;
if(t==ii)
{
if(pd(a[ii],a[1]))print(); //判断+打印
}
else search(t+1); //递归
b[i]=0; //把bool b从新赋值为0,这里是回溯的思想
}
}
// return 0;
//和上面的print函数的retur 0原因一样。
}
int main()
{
int c=1; //定义一个计数器,输出的时候让输出Case n:。
while(~scanf("%d",&ii)) //多组输入
{
printf("Case %d:\n",c);
search(1);
printf("\n"); //题目要求每组后面多一个换行
c++; //每次输入完后计数器加一
}
return 0;
}
D - Oil Deposits
原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1241
完整代码:
#include<stdio.h>
#include<string.h>
char map[110][110];//储存数据
int n,m;
//八个方位
int vis[8][2]={{-1,-1},{-1,0},{-1,1},{0,1},{0,-1},{1,1},{1,0},{1,-1}};
void dfs(int x,int y) //深度优先搜索
{
map[x][y]='*';//搜索过的@都变为*
for(int i=0;i<8;i++)
{
//下一个点的坐标
int dx=x+vis[i][0];
int dy=y+vis[i][1];
if(dx<0||dx>=n||dy<0||dy>=m)//判断是否越界
{
continue;
}
if(map[dx][dy]=='@')
{
dfs(dx,dy);//开始尝试下一个点
}
}
}
int main()
{
while(~scanf("%d %d",&n,&m))
{
memset(map,0,sizeof(map));
if(m==0)
break;
for(int i=0;i<n;i++)
{
scanf("%s",map[i]);
}
int sum=0;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(map[i][j]=='@')//查找
{
sum++;
dfs(i,j);
}
}
}
printf("%d\n",sum);
}
return 0;
}
E - 迷宫问题
原题链接:http://poj.org/problem?id=3984
完整代码:
#include<stdio.h>
#include<queue>
#include<string.h>
using namespace std;
int dir[4][2] = { {1,0}, {-1,0}, {0,-1}, {0,1}}; //上下左右移动,四个方位
int num[5][5]; //储存数据
struct node
{
int x, y;
}v[5][5]; //结构体数组(x,y)坐标
void DFS(int x, int y) //深度优先搜索
{
if(x == 0 && y ==0) //如果是起点(0,0)
{
return;
}
DFS(v[x][y].x, v[x][y].y); //递归
printf("(%d, %d)\n",v[x][y].x, v[x][y].y); //打印坐标
}
void BFS(node s) //广度优先搜索(s为坐标(结构体型变量))
{
node t, q; //定义两个结构体变量
queue<node>Q; //定义一个队列,用队列存数据
Q.push(s); //入队(把坐标存入队列)
while(Q.size()) //如果队列不为空
{
q = Q.front(); //队首元素赋给q
Q.pop(); //出列
if(q.x == 4 && q.y == 4) //坐标为终点
{
DFS(q.x, q.y); //开始尝试下一个点
printf("(%d, %d)\n",q.x,q.y); //打印终点坐标
return;
}
for(int i = 0; i<4; i++)
{
t = q; //关键之笔,让同一个位置走四次不同的方向
//计算下一点的坐标
t.x += dir[i][0];
t.y += dir[i][1];
if(t.x >=0 && t.y >=0 && t.x <5 && t.y <5 && num[t.x][t.y] == 0)//判断是否越界,都在[5][5]之内,
{ //且不能是走过的路或者是墙。
v[t.x][t.y].x = q.x;
v[t.x][t.y].y = q.y;
num[t.x][t.y] = 1; //把走过的都变成墙(把0变成1)
Q.push(t); //入列
}
}
}
}
int main(void)
{
for(int i = 0; i<5; i++)
{
for(int j = 0; j<5; j++)
{
scanf("%d",&num[i][j]); //输入二维数组地图
}
}
memset(v, 0, sizeof(v)); //清空数组
node s; //定义一个结构体型的变量
//初始化(x,y),坐标从(0,0)开始
s.x = 0;
s.y = 0;
BFS(s); //调用BFS函数
return 0;
}
F - Tempter of the Bone
原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1010
完整代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
char Map[10][10]; //地图
int visit[10][10]; //储存数据
int n,m,t,endx,endy,flag; //n、m、结束坐标、标记
void dfs(int startx,int starty,int time) //开始坐标,时间
{
int dx,dy;
int dir[4][2]={{-1,0},{1,0},{0,1},{0,-1}}; //上下左右四个方向
if(flag) //***很重要,可以减少步骤,如果直接找到路线就直接跳出
{
return;
}
if(startx==endx&&starty==endy&&time==t)
{
flag=1;
return;
}
int temp=t-time-abs(endx-startx)-abs(endy-starty); //剪枝代码
if(temp<0||temp&1) //如果剩余的步数已经不足以走到出口,且必须是偶数,偶数-偶数=偶数,奇数-奇数=偶数
{
return;
}
for(int i=0;i<4;i++)
{
dx=startx+dir[i][0];
dy=starty+dir[i][1];
if(dx<0||dy>=m||dy<0||dx>=n)
{
continue;
}
if(Map[dx][dy]!='X'&&visit[dx][dy]==0)
{
visit[dx][dy]=1; //标记,判断能不能走
dfs(dx,dy,time+1);
if(flag) //找到就return
return;
visit[dx][dy]=0; //返回标记,方便下次寻找
}
}
return ;
}
int main()
{
int startx,starty,wall; //开始坐标、墙
while(cin>>n>>m>>t)
{
if(n==0&&m==0&&t==0)
{
break;
}
flag=0;wall=0;
memset(visit,0,sizeof(visit));
for(int i=0;i<n;i++) //画地图
{
scanf("%s",Map[i]);
}
for(int i=0;i<n;i++) //判断
{
for(int j=0;j<m;j++)
{
if(Map[i][j]=='S')
{
startx=i;starty=j;
}
if(Map[i][j]=='D')
{
endx=i;endy=j;
}
if(Map[i][j]=='X')
{
wall++;
}
}
}
if(t>n*m-wall-1) //判断时间与墙数和地图的关系
{
cout<<"NO"<<endl;
continue;
}
visit[startx][starty]=1; //标记走过的路线
dfs(startx,starty,0);
if(flag==1)
{
cout<<"YES"<<endl;
}
else
{
cout<<"NO"<<endl;
}
}
return 0;
}