dfs
- 迷宫问题
- 联通块问题
- 排列问题
- 关于枝剪:寻找枝剪特征,以枝剪特征为依据去枝剪
- 可行性枝剪 (上下界)
- 最优性枝剪
- 记忆化
- dfs的缺陷:不达底部不罢休!
例题:
房间里放着n块奶酪。一只小老鼠要把它们都吃掉,问至少要跑多少距离?老鼠一开始在(0,0)点处。
输入:
4 1 1 1 -1 -1 1 -1 -1
输出:
7.41
#include<bits/stdc++.h>
#define maxn 100000+5
#define mst(a) memset(a,0,sizeof a)
#define ll long long
using namespace std;
//题号:
//问题:
//解法:两点之间的距离公式=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))
/*总结: 结构体重载运算符 枝剪 记忆化搜索 */
struct point
{
double x,y;
double operator-(const point a)
{
return sqrt((this->x-a.x)*(this->x-a.x)+(this->y-a.y)*(this->y-a.y));
}
}A[20];
int vis[20];
double dis[20][20];
double minn = INF,n;
void dfs(int t,int p,double sum)
{
if(sum>minn)return;//这个也是一个重要的枝剪
if(t==n)
{
if(sum<minn)minn = sum;
}
for(int i = 1;i<=n;i++)
if(!vis[i])
{
if(!dis[p][i])
{
dis[i][p] = dis[p][i] = A[p]-A[i]; //记忆化,也可以做预处理
}
vis[i] = 1;
dfs(t+1,i,sum+dis[p][i]);
vis[i] = 0;
}
}
int main()
{
ios::sync_with_stdio(false);
cin>>n;
mst(vis);
mst(dis);
A[0].x = 0,A[0].y = 0;
for(int i = 1; i<=n; i++)
cin>>A[i].x>>A[i].y;
dfs(0,0,0);
printf("%.2lf",minn);
return 0;
}
bfs搜索
- 最短路(权值为1)
- 状态转移
#include<iostream>
#include<cstring>
#include<queue>
#include<stack>
#define maxn 20005
#define INF 0x3f3f3f3f
#define mst(a) memset(a,0,sizeof a)
#define ll long long
using namespace std;
struct cup
{
//x y为杯子
//sp 步数 fg:flag
//prev:记录路径
int x,y;
int sp,fg;
cup* prev;
}t[10020];
queue<cup>Q;
stack<int>R;
int vis[150][150];
int a,b,k;
int ans = 0;
void bfs(int x,int y)
{
cup c ;
c.x = x, c.y = y;
c.sp = 0, c.fg = 0;
c.prev = NULL;
vis[x][y] = 1;
Q.push(c);
int num = -1;
while(!Q.empty())
{
// cout<<c.x<<ends <<c.y<<endl;
num++;
t[num] = Q.front();
Q.pop();
for(int i = 1; i <= 6; ++i)
{
switch(i)
{
case 1://fill a
c.x = a;
c.y = t[num].y;
c.fg = 1;
break;
case 2://fill b
c.y = b;
c.x = t[num].x;
c.fg = 2;
break;
case 3://drop a
c.x = 0;
c.y = t[num].y;
c.fg = 3;
break;
case 4://drop b
c.y = 0;
c.x = t[num].x;
c.fg = 4;
break;
case 5://pour a to b
if(c.x+c.y> b)
{
c.y = b;
c.x = t[num].x + t[num].y - b;
}
else
{
c.y = t[num].y + t[num].x;
c.x = 0;
}
c.fg = 5;
break;
case 6://pour b to a
if(c.x+c.y> a)
{
c.x = a;
c.y = t[num].y + t[num].x - a;
}
else
{
c.x = t[num].x + t[num].y;
c.y = 0;
}
c.fg = 6;
break;
}
if(vis[c.x][c.y])continue;
vis[c.x][c.y] = 1;
c.sp = t[num].sp+1;
c.prev = &t[num];
if(c.x == k ||c.y == k)
{
ans = c.sp;
while(c.prev)
{
R.push(c.fg);
c = *c.prev;
}
return ;
}
Q.push(c);
}
}
}
void print()
{//输出路径
while(!R.empty())
{
int i = R.top();
R.pop();
switch(i)
{
case 1:cout<<"FILL(1)"<<endl;break;
case 2:cout<<"FILL(2)"<<endl;break;
case 3:cout<<"DROP(1)"<<endl;break;
case 4:cout<<"DROP(2)"<<endl;break;
case 5:cout<<"POUR(1,2)"<<endl;break;
case 6:cout<<"POUR(2,1)"<<endl;break;
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin>>a>>b>>k;
mst(vis);
bfs(0,0);
if(!ans)
{
cout<<"impossible"<<endl;
}
else
{
cout<< ans <<endl;
print();
}
return 0;
}