1搜索回溯问题
Q - 真·水题 OpenJ_Bailian - 4127
定义一个二维数组:
int maze[5][5] = {
0, 1, 0, 0, 0,
0, 1, 0, 1, 0,
0, 0, 0, 0, 0,
0, 1, 1, 1, 0,
0, 0, 0, 1, 0,
};
它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。
Input
一个5 × 5的二维数组,表示一个迷宫。数据保证有唯一解。
Output
左上角到右下角的最短路径,格式如样例所示。
Sample Input
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0
Sample Output
(0, 0)
(1, 0)
(2, 0)
(2, 1)
(2, 2)
(2, 3)
(2, 4)
(3, 4)
(4, 4)
题目简述:迷宫问题给出起点到终点 求最短路径的每步坐标
题目解析:广搜+回溯
代码如下:
#include<stdio.h>
int i,j,head,tail,a[101][101],book[101][101];
struct map
{
int x;
int y;
int c;
}que[101];
print(int head)
{
while(que[head].c!=-1)
{
print(que[head].c);
printf("(%d, %d)\n",que[head].x,que[head].y);
return 0;
}
printf("(0, 0)\n");
}
int main()
{
int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
struct map ass;
for(i=0;i<5;i++)
for(j=0;j<5;j++)
scanf("%d",&a[i][j]);
head=0,tail=1;
que[0].x=0;
que[0].y=0;
que[0].c=-1;
while(head<tail)
{
if(que[head].x==4&&que[head].y==4)
{
print(head);
break;
}
for(i=0;i<4;i++)
{
ass.x=que[head].x+dir[i][0];
ass.y=que[head].y+dir[i][1];
ass.c=head;//用于回溯
if(ass.x<0||ass.x>5||ass.y<0||ass.y>5)
continue;
if(book[ass.x][ass.y]==0&&a[ass.x][ass.y]==0)
{
book[ass.x][ass.y]=1;
que[tail]=ass;//结构体可以整体赋值
tail++;
}
}
head++;
}
}
2搜索
A - 平行宇宙 POJ - 1426
在2100年科学家发现了平行宇宙,但是新发现的Earth2的世界中所有数字都是由0和1组成的十进制数,如果从我们的世界穿越到Earth2,数字将发生一些变化,例如:一个正整数n,将被转化为n的一个非零的倍数m,这个m应当符合Earth2的数字规则。你可以假定n不大于200且m不多于100位。
提示:本题采用Special Judge,你无需输出所有符合条件的m,你只需要输出任一符合条件的m即可。
Input
输入包含多组数据,每组数据仅一行,只包含一个正整数n,n==0时输入结束 (1 <= n <= 200).
Output
对于输入的每组n,都输出任一符合条件的m。即使有多个符合条件的m,你也只需要输出一个即可。
(已知long long范围内存在表示数据中所有的m
Sample Input
2
6
19
0
Sample Output
10
100100100100100100
111111111111111111
题目简述:找一个由1和0组成的并且是所给数据的倍数的数
题目解析:广搜即可,dfs(ans10)和dfs(ans10+1)注意当找到一个符合的数就需要退出 flag的作用就是一层层结束
代码如下
#include<stdio.h>
int n;
int flag=0;
int dfs(long long int ans,int cnt)
{
if(flag==1)
return 0;
if(ans%n==0)
{
printf("%lld\n",ans);
flag=1;
return 0;
}
if(cnt>=19)return 0;
dfs(ans*10,cnt+1);
dfs(ans*10+1,cnt+1);
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
if(n==0)
break;
flag=0;
dfs(1,1);
}
}
3 搜索
B - 马走日 OpenJ_Bailian - 4123
马在中国象棋以日字形规则移动。
请编写一段程序,给定n*m大小的棋盘,以及马的初始位置(x,y),要求不能重复经过棋盘上的同一个点,计算马可以有多少途径遍历棋盘上的所有点。
Input
第一行为整数T(T < 10),表示测试数据组数。
每一组测试数据包含一行,为四个整数,分别为棋盘的大小以及初始位置坐标n,m,x,y。(0<=x<=n-1,0<=y<=m-1, m < 10, n < 10)
Output
每组测试数据包含一行,为一个整数,表示马能遍历棋盘的途径总数,0为无法遍历一次。
Sample Input
1
5 4 0 0
Sample Output
32
题目简述:给出起点 问全部遍历棋盘上的点的路径个数
题目解析:dfs 统计步数 步数满足棋盘大小sum++ 一个点可遍历多次所以需要取消标记
代码如下
#include<stdio.h>
int vis[10][10],n,m,sum;
void dfs(int x,int y,int cnt)
{
int dir[8][2]={{1,2},{1,-2},{-1,-2},{-1,2},{2,1},{2,-1},{-2,1},{-2,-1}};
if(cnt>=n*m)
sum++;
for(int i=0;i<8;i++)
{
int tx=x+dir[i][0];
int ty=y+dir[i][1];
if(tx>=0&&tx<n&&ty>=0&&ty<m&&vis[tx][ty]==0)
{
vis[tx][ty]=1;
dfs(tx,ty,cnt+1);
vis[tx][ty]=0;
}
}
}
int main()
{
int t,x,y,i,j;
scanf("%d",&t);
while(t--)
{
for(i=0;i<10;i++)
for(j=0;j<10;j++)
vis[i][j]=0;
scanf("%d %d %d %d",&n,&m,&x,&y);
vis[x][y]=1;
sum=0;
dfs(x,y,1);
printf("%d\n",sum);
}
return 0;
}
4 搜索
C - 棋盘问题 POJ - 1321
在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。
Input
输入含有多组测试数据。
每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n
当为-1 -1时表示输入结束。
随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。
Output
对于每一组数据,给出一行输出,输出摆放的方案数目C (数据保证C<2^31)。
Sample Input
2 1
#.
.#
4 4
…#
…#.
.#…
#…
-1 -1
Sample Output
2
1
题目简述:求将棋子放不同列 不同行的方案数
题目解析:深搜 搜索下一行 cnt记录所走行数 当cnt达到棋盘的行数 sum++
代码如下
#include<stdio.h>
char c[9][9];
int vis[101],n,k,sum;
void dfs(int x,int cnt)
{
if(k==cnt)
{
sum++;
return ;
}
for(int i=x;i<n;i++)//注意i是从x开始遍历的
for(int j=0;j<n;j++)
{
if(c[i][j]=='#'&&vis[j]==0)
{ vis[j]=1;
dfs(i+1,cnt+1);
vis[j]=0;
}
}
}
int main()
{
while(scanf("%d%d",&n,&k))
{
if(n==-1&&k==-1)
break;
for(int i=0;i<n;i++)
scanf("%s",&c[i]);
sum=0;
for(int i=0;i<101;i++)
vis[i]=0;
dfs(0,0);
printf("%d\n",sum);
}
return 0;
}
5 二分
POJ - 2456
在彩虹岛的湖里有C只鹅,所以ww建造了一座包括N个隔间的畜栏,分别在坐标轴上的x1…xN位置,但这些鹅都彼此看不惯对方,为了防止他们互相伤害,所以不能把几只鹅放在一个隔间里,而且还应该使两只鹅之间的最小距离尽可能的大,可ww思考了好久,都不知道这个最大的最小距离是多少,你能不能帮帮他呢?
数据范围:2<=N<=100000, 0<=xi<=1000000000, 2<=C<=N
Input
有多组测试数据,以EOF结束。
第一行包含两个整数N和C
后面接着有N行,分别表示xi的位置。
Output
每组测试数据输出一个整数,即题目中所说的最大的最小值。
Sample Input
5 3
1
2
8
4
9
Sample Output
3
题目简述:求最小距离最大化
题目解析:二分确定距离 check函数判断是否符合题意
#include<stdio.h>
#include<algorithm>
using namespace std;
long long int n,c;
long long int a[100001],i;
int fact(long long int d)
{
int ass=a[0];
int sum=1;
for(i=1;i<n;i++)
{
if(a[i]-ass>=d)
{
sum++;
ass=a[i];
}
}
if(sum>=c)
return 1;
return 0;
}
int main()
{
long long int min,max,mid;
while(scanf("%lld %lld",&n,&c)!=EOF)
{ for(i=0;i<n;i++)
scanf("%lld",&a[i]);
sort(a,a+n);
max=a[n-1]-a[0];
min=0;
while(max-min>1)
{
mid=(max+min)/2;
if(fact(mid))
min=mid;
else
max=mid;
}
printf("%lld\n",min);
}
}
6二分
HDU - 2899
Now, here is a fuction:
F(x) = 6 * x7+8*x6+7x3+5*x2-yx (0 <= x <=100)
Can you find the minimum value when x is between 0 and 100.
Input
The first line of the input contains an integer T(1<=T<=100) which means the number of test cases. Then T lines follow, each line has only one real numbers Y.(0 < Y <1e10)
Output
Just the minimum value (accurate up to 4 decimal places),when x is between 0 and 100.
Sample Input
2
100
200
Sample Output
-74.4291
-178.8534
题目简述:给出y的值以及x的范围(1到100)求方程值的最小值
题目解析:找方程值最小对应的x是关键 通过二分找导函数等于0 可以找出这个x
代码如下
#include<stdio.h>
#include<math.h>
double y;
double ans(double i)
{
return 6*pow(i,7)+8*pow(i,6)+7*pow(i,3)+5*i*i-y*i;
}
double fact(double i)
{
return 42*pow(i,6)+48*pow(i,5)+21*i*i+10*i-y;
}
int main()
{
double left,right,mid;
int x;
scanf("%d",&x);
while(x--)
{
scanf("%lf",&y);
left=0.0,right=100.0;
while(right-left>1e-7)
{
mid=(right+left)/2;
if(fact(mid)<0)
left=mid;
else
right=mid;
}
printf("%0.4lf\n",ans(mid));
}
}
有一间长方形的房子,地上铺了红色、黑色两种颜色的正方形瓷砖。你站在其中一块黑色的瓷砖上,只能向相邻的黑色瓷砖移动。请写一个程序,计算你总共能够到达多少块黑色的瓷砖。
Input
包括多个数据集合。每个数据集合的第一行是两个整数W和H,分别表示x方向和y方向瓷砖的数量。W和H都不超过20。在接下来的H行中,每行包括W个字符。每个字符表示一块瓷砖的颜色,规则如下
1)‘.’:黑色的瓷砖;
2)‘#’:白色的瓷砖;
3)‘@’:黑色的瓷砖,并且你站在这块瓷砖上。该字符在每个数据集合中唯一出现一次。
当在一行中读入的是两个零时,表示输入结束。
Output
对每个数据集合,分别输出一行,显示你从初始位置出发能到达的瓷砖数(记数时包括初始位置的瓷砖)。
Sample Input
6 9
…#.
…#
…
…
…
…
…
#@…#
.#…#.
0 0
Sample Output
45
题目简述:给出起点求遍历迷宫的最大步数
题目解析:典型dfs
下面这个代码没有a过 显示wrong answer 用例可以过 自己实在没找出错哪了 哪位大佬如果能看出来还请指点指点
#include<stdio.h>
int cnt=0,i,j;
int n,m;
int book[101][101];
char map[101][101];
void dfs(int x,int y)
{
cnt++;
book[x][y]=1;
int dir[4][2]={{0,-1},{0,1},{1,0},{-1,0}};
for(int k=0;k<4;k++)
{
int tx=x+dir[k][0];
int ty=y+dir[k][1];
if(tx<0||ty<0||tx>m||ty>n)
continue;
if(book[tx][ty]==0&&map[tx][ty]=='.')
{
dfs(tx,ty);
}
}
}
int main()
{
while(scanf("%d %d",&m,&n)!=EOF)
{
cnt=0;
if(m==0&&n==0)
return 0;
for(i=0;i<n;i++)
scanf("%s",map[i]);
for(i=0;i<n;i++)
for(j=0;j<m;j++)
if(map[i][j]=='@')
{
//printf("%d %d",i,j);
dfs(i,j);
break;
}
printf("%d\n",cnt);
for(i=0;i<101;i++)
for(j=0;j<101;j++)
book[i][j]=0;
}
}