搜索
搜索
DFS(递归)
找边界条件 找递推关系
快速幂
int kuaisumi(int a,int k)
{
if(k==0)return 1;
int ha=ksm(a,k/2);
if(k%2==1)return ha*ha*a;
else return ha*ha;
}
因为简单的递归会存在大量的重复调用,我们可以进行存储,下次调用时可以直接使用。将复杂度从指数级降为O(n)
int f[maxn];
int F(int x)
{
if(x==1)return 1;
if(x==2)return 1;
if(f[x]!=-1)return f[x];
f[x]=F(x-1)+F(x-2);
return f[x];
}
洛谷P1162
洛谷1605
N*M的迷宫,T处障碍,可上下左右移动,求起点到终点的方案数/最小步数
回溯法
void dfs(int x,int y)//,int d
{
if(这个点是终点)
{
方案数++;//ans=min(ans,d);
return ;
}
标记(x,y)已走过
枚举下一步要走的点
{
if(这个点能走)
{
dfs(下一个点)//,d+1
}
}
取消(x,y)的标记
}
N皇后问题
https://www.cnblogs.com/henuliulei/p/10117304.html
POJ 1321
在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。
Input
输入含有多组测试数据。
每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n
当为-1 -1时表示输入结束。
随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。
Output
对于每一组数据,给出一行输出,输出摆放的方案数目C (数据保证C<2^31)。
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
typedef long long LL;
using namespace std;
//跟N皇后问题差不多 但是可能出现某一列不放的情况,所以要多加一个循环进行一个判断
const int maxn=1e5+5;
int cnt=0,n,k,vis[15];
char c[15][15];
int DFS(int a,int b)
{
if(k==b){cnt++;return 0;}
for(int i=a;i<n;i++)//按行来放就不用判断i
{
for(int j=0;j<n;j++)
{
if(!vis[j]&&c[i][j]=='#')
{
vis[j]=1;
DFS(i+1,b+1);
vis[j]=0;
}
}
}
return 0;
}
int main()
{
while(cin>>n>>k)
{
memset(vis,0,sizeof(vis));
memset(c,0,sizeof(c));
if(n==-1&&k==-1)break;
for(int i=0;i<n;i++)cin>>c[i];
cnt=0;DFS(0,0);
cout<<cnt<<endl;
}
return 0;
}
Knight‘s Trip
/**
首先,xy的大小排序和转化为都是正数步数不变应该懂吧。
y=2*x这种情况直接就是(x+y)/3步。
如果y<2*x但是(x+y)%3==0的话,那么我们可以通过控制(1,2),(2,1)
两种跳法的次数达到...总数必然是(x+y)/3,然后xy的和对3取余是1的话,
我们是不是必然可以在(x+y-1)/3步的时候跳到(x,y-1)这个点,但是不能一步
跳到(x,y),回撤两步到(x-4,y-5)这个点,我们可以用三步跳到(x,y),那么
就是原先的步数+1。余数为2,就是先跳到(x-1,y-1)这个地方,我们知道(0,0)
到(1,1)只需要两步,那么(x-1,y-1)到(x,y)也就是原先步数+2.然后考虑y>2*x,
先把(0,1)的情况特殊处理一下。接着我们可以用x步跳到(x,y),那么原问题就
转化为(0,0)到(0,y-2*x)。当y-2*x是4的倍数的话我们可以直接(1,2)(-1,2)这个
跳可以在(y-2*x)/2步到达。余数为1,就是(0,0)到(0,1)的问题,但是这个需要
三步不是最优的,我们后撤两步变为(0,0)到(0,5),我们可以三步达到,那么就
是原先的步数加上1就是解。余数为2,我们可以分别跳一次(2,1)(-2,1)到达。
余数为3,转化为(0,0)到(0,3)的问题我们可以(-1,2)(1,1)(0,3)三步到达。
以上就是全部情况,o(╯□╰)o,在纸上画画,应该所有在这这几类范围内。
**/
#include <bits/stdc++.h>
typedef long long LL;
using namespace std;
int main()
{
char c[20];
while(scanf("%s",c),strcmp(c,"END"))
{
int x,y,ans;
sscanf(c,"%d",&x);
cin>>y;
x=abs(x);y=abs(y);
if(y<x) {swap(x,y);}
if(y<=2*x)
{
if(x==1&&y==1)cout<<2<<endl;
else if(x==2&&y==2)cout<<4<<endl;
else cout<<(x+y)/3+(x+y)%3<<endl;
}
else
{
ans=x+(y-2*x)%4+(y-2*x-(y-2*x)%4)/2;
if(y==1&&x==0)cout<<3<<endl;
else cout<<ans<<endl;
}
}
return 0;
}
POJ2676
http://poj.org/problem?id=2676
要求在一个9*9的矩阵中,每一行,每一列都不能出现相同的数字,并且在这个9*9的矩阵中分成的9个3*3的小矩阵中数字也不可以重复。输出要求的矩阵,其中矩阵的一些数字已经给出。
BFS
数据结构:队列(先进先出)
操作:入队、出队、获取队首元素、判断队列是否为空
一般使用:STL中的queue (头文件#include
struct Node{
int x;
};
queue<Node> q;
int main()
{
q.push(1);//1入队
q.push(2);//2入队
cout<<q.front<<endl;//获取队首元素 此时为1
q.pop();//1出队
cout<<q.front<<endl;//获取队首元素 此时为2
cout<<q.empty<<endl;//判断队列是否为空 是为1 否为0
}
解题一般步骤(BFS过程)
- 将起点入队
- 取出队首元素
- 将该点周围可以走的格子入队
- 返回2.
Red and black
https://blog.csdn.net/Peppame/article/details/103645341
POJ 1426
Given a positive integer n, write a program to find out a nonzero multiple m of n whose decimal representation contains only the digits 0 and 1. You may assume that n is not greater than 200 and there is a corresponding m containing no more than 100 decimal digits.
Input
The input file may contain multiple test cases. Each line contains a value of n (1 <= n <= 200). A line containing a zero terminates the input.
Output
For each value of n in the input print a line containing the corresponding value of m. The decimal representation of m must not contain more than 100 digits. If there are multiple solutions for a given value of n, any one of them is acceptable.
#include <bits/stdc++.h>
typedef long long LL;
using namespace std;
const int maxn=1e5+5;
queue <LL> q;
LL x,n ;
void bfs()
{
while(!q.empty())q.pop();//清空
q.push(1);//n>=1
while(1)
{
x=q.front(); //一个一个判断
if(x%n==0){cout<<x<<endl;return;}
q.pop(); //判断完就丢掉
q.push(x*10);
q.push(x*10+1); //将两种都放进去
}
}
int main()
{
while(cin>>n)
{
if(n==0)
break;
bfs();
}
return 0;
}
hdu 2102
可怜的公主在一次次被魔王掳走一次次被骑士们救回来之后,而今,不幸的她再一次面临生命的考验。魔王已经发出消息说将在T时刻吃掉公主,因为他听信谣言说吃公主的肉也能长生不老。年迈的国王正是心急如焚,告招天下勇士来拯救公主。不过公主早已习以为常,她深信智勇的骑士LJ肯定能将她救出。
现据密探所报,公主被关在一个两层的迷宫里,迷宫的入口是S(0,0,0),公主的位置用P表示,时空传输机用#表示,墙用*表示,平地用.表示。骑士们一进入时空传输机就会被转到另一层的相对位置,但如果被转到的位置是墙的话,那骑士们就会被撞死。骑士们在一层中只能前后左右移动,每移动一格花1时刻。层间的移动只能通过时空传输机,且不需要任何时间。
Input
输入的第一行C表示共有C个测试数据,每个测试数据的前一行有三个整数N,M,T。 N,M迷宫的大小NM(1 <= N,M <=10)。T如上所意。接下去的前NM表示迷宫的第一层的布置情况,后N*M表示迷宫第二层的布置情况。
Output
如果骑士们能够在T时刻能找到公主就输出“YES”,否则输出“NO”。
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
typedef long long LL;
using namespace std;
char a[2][15][15];
int n,m,T,count,dir[4][2]={
{1,0},
{0,1},
{-1,0},
{0,-1}
};
int vis[2][15][15];
struct node
{
int x,y,l,t;
};
queue<node>q;
void BFS()
{
node b,c;
b.x=0,b.y=0,b.l=0,b.t=0;
vis[b.l][b.x][b.y]=1;
q.push(b);
while(!q.empty())
{
b=q.front();//取来判断
if(b.t>T){cout<<"NO"<<endl;return;}//T不够
if(a[b.l][b.x][b.y]=='P'&&b.t<=T){cout<<"YES"<<endl;return ;}//成功救出
for(int i=0;i<4;i++)//询问四个方向
{
c.x=b.x+dir[i][0];c.y=b.y+dir[i][1];c.l=b.l; //楼层不变
if((c.x<0||c.x>=n||c.y<0||c.y>=m)||a[c.l][c.x][c.y]=='*'||vis[c.l][c.x][c.y])continue;//不能走(边缘、有墙、已走过)
c.t=b.t+1;//计时
vis[c.l][c.x][c.y]=1;//标记走过的
if(a[!c.l][c.x][c.y]!='*'&&a[c.l][c.x][c.y]=='#'&&a[!c.l][c.x][c.y]!='#')//传送
{
c.l=1-c.l,c.t=b.t+1;
vis[c.l][c.x][c.y]=1;
q.push(c);
}
else if(a[c.l][c.x][c.y]=='.'||a[c.l][c.x][c.y]=='P') q.push(c);
}
q.pop();//踢除
}
cout<<"NO"<<endl;
}
int main()
{
int C,i,j;
cin>>C;
while(C--)
{
cin>>n>>m>>T;
for(i=0;i<n;i++)cin>>a[0][i];getchar();
for(i=0;i<n;i++)cin>>a[1][i];
memset(vis,0,sizeof(vis));
while(!q.empty())q.pop();
BFS();
}
}
HDU-1548
BFS对于求无权路的最短路径很方便,遍历一遍,到了对应的节点,则可以说是最短路径,对于有权图可以采用Dijkstra等等。
Problem Description
There is a strange lift.The lift can stop can at every floor as you want, and there is a number Ki(0 <= Ki <= N) on every floor.The lift have just two buttons: up and down.When you at floor i,if you press the button "UP" , you will go up Ki floor,i.e,you will go to the i+Ki th floor,as the same, if you press the button "DOWN" , you will go down Ki floor,i.e,you will go to the i-Ki th floor. Of course, the lift can't go up high than N,and can't go down lower than 1. For example, there is a buliding with 5 floors, and k1 = 3, k2 = 3,k3 = 1,k4 = 2, k5 = 5.Begining from the 1 st floor,you can press the button "UP", and you'll go up to the 4 th floor,and if you press the button "DOWN", the lift can't do it, because it can't go down to the -2 th floor,as you know ,the -2 th floor isn't exist.
Here comes the problem: when you are on floor A,and you want to go to floor B,how many times at least he has to press the button "UP" or "DOWN"?
Input
The input consists of several test cases.,Each test case contains two lines.
The first line contains three integers N ,A,B( 1 <= N,A,B <= 200) which describe above,The second line consist N integers k1,k2,....kn.
A single 0 indicate the end of the input.
Output
For each case of the input output a interger, the least times you have to press the button when you on floor A,and you want to go to floor B.If you can't reach floor B,printf "-1".
Sample Input
5 1 5
3 3 1 2 5
0
Sample Output
3
奇怪的电梯题目输入是当前所在楼层,目的楼层,楼层总数,每层电梯只能上下的层数。输出到达目标楼层最少的次数,不能到达则-1。

浙公网安备 33010602011771号