力推这篇博客!非常感谢,写的很详细 https://blog.csdn.net/yoer77/article/details/53707149
附上代码:
#include<bits/stdc++.h>
using namespace std;
#define runfile freopen("E:/Code/CB/Root/data.txt", "r", stdin)
#define stopfile fclose(stdin)
struct People
{
int pos;
bool lifted;//正在被举着
bool lifting;//正在举着别人
int lift;//举着的是谁
int maxMove;//最大的可移动的距离
int maxThrow;//最大的可扔出的距离
bool hasMoved;//是否移动过
bool haslifted;//是否举过别人
}p[3];
bool vis[10],pos[50];
//3个人每人3个动作,一共9个操作。全排列这9个操作,标记重复
//标记数轴的每个位置是否有人
int ans = 0;
void dfs(int k, int step)
{
int n = k/3;//当前执行的人
int m = k%3;//当前执行的动作
//move
if(!m)
{
//如果他正在举着别人、正在被举着、已经移动过,那么他都不能移动
if(p[n].lifting || p[n].lifted || p[n].hasMoved) return;
int i = 1;
if(step == 9) i = p[n].maxMove;//如果当前是最后一步,那么直接可以移动到最远的距离
//如果不是最后一步,那么他也不必要从他能移动的最靠后的距离开始搜索
//他只需要从 他的位置之前的 有人的位置 的前一个位置 开始搜索即可
//如果他后面没人,那么他走的距离只需要从 1 开始搜索,不需要往后面走,只需要往前走
else
{
for(int j = 1; j < p[n].pos; j++)
{
if(pos[j])
{
int l = -(p[n].pos - j - 1);
i = min(l, i);
}
}
i = max(-p[n].maxMove, i);//走的距离不能超过maxMove
}
for(; i <= p[n].maxMove; i++)
{
//决定要移动到这个位置,必须是该位置的左右有人或者是该位置为这个人的最大移动的距离
if(pos[p[n].pos+i-1] || pos[p[n].pos+i+1] || i == p[n].maxMove)
{
if(p[n].pos + i > 0 && !pos[p[n].pos + i])
{
if(!i) continue;
pos[p[n].pos] = false;//当前位置设置为false
p[n].pos += i;//向前走
pos[p[n].pos] = true;//走到的新位置置为true
p[n].hasMoved = true;//标记为已经移动过
ans = max(p[n].pos, ans);
//继续搜索
for(int j = 0; j < 9; j++)
{
if(!vis[j])
{
vis[j] = true;
dfs(j, step+1);
vis[j] = false;//回溯
}
}
//回溯
p[n].hasMoved = false;
pos[p[n].pos] = false;
p[n].pos -= i;
pos[p[n].pos] = true;
}
}
}
}
//lift
else if(m == 1)
{
//如果当前这个人正在被举着或者真在举着别人,或者已经举起过别人了,那么他不能再将别人举起
if(p[n].lifted || p[n].lifting || p[n].haslifted) return;
for(int i = 0; i < 3; i++)
{
//如果旁边有人
if(abs(p[i].pos - p[n].pos) == 1)
{
//如果旁边的这个人已经被别人举起了,则不能重复举起
if(p[i].lifted) continue;
p[n].haslifted = true;
p[n].lifting = true;
p[n].lift = i;
p[i].lifted = true;
int temp = p[i].pos;
pos[p[i].pos] = false;
p[i].pos = p[n].pos;
//如果当前举起的人正在举着其他人,那么这两个人的位置必须同步修改
if(p[i].lifting)
{
int j = p[i].lift;
p[j].pos = p[i].pos;
}
//继续搜索
for(int j = 0; j < 9; j++)
{
if(!vis[j])
{
vis[j] = true;
dfs(j, step+1);
vis[j] = false;
}
}
//回溯
p[n].haslifted = false;
p[n].lifting = false;
p[n].lift = -1;
p[i].lifted = false;
p[i].pos = temp;
pos[p[i].pos] = true;
if(p[i].lifting)
{
int j = p[i].lift;
p[j].pos = p[i].pos;
}
}
}
}
//throw
else
{
//如果当前这个人正在被举起,或者他没有举起别人,那么他不能执行抛的动作
if(!p[n].lifting || p[n].lifted) return ;
int i = 1;
if(step == 9) i = p[n].maxThrow;
else
{
for(int j = 1; j < p[n].pos; j++)
{
if(pos[j])
{
int l = -(p[n].pos - j - 1);
i = min(l, i);
}
}
i = max(i, -p[n].maxThrow);
}
for(; i <= p[n].maxThrow; i++)
{
if(p[n].pos + i > 0 && !pos[p[n].pos+i])
{
if(pos[p[n].pos+i-1] || pos[p[n].pos+i+1] || i == p[n].maxThrow)
{
int j = p[n].lift;
p[j].pos += i;
p[n].lifting = false;
p[n].lift = -1;
p[j].lifted = false;
pos[p[j].pos] = true;
ans = max(p[j].pos, ans);
if(p[j].lifting)
{
int k = p[j].lift;
p[k].pos = p[j].pos;
}
for(int q = 0; q < 9; q++)
{
if(q == k) continue;
if(!vis[q])
{
vis[q] = true;
dfs(q, step + 1);
vis[q] = false;
}
}
//回溯
pos[p[j].pos] = false;
p[j].pos -= i;
p[j].lifted = true;
p[n].lift = j;
p[n].lifting = true;
if(p[j].lifting)
{
int k = p[j].lift;
p[k].pos = p[j].pos;
}
}
}
}
}
}
int main()
{
// runfile;
ios::sync_with_stdio(false);
memset(vis, 0, sizeof(vis));
memset(pos, 0, sizeof(pos));
for(int i = 0; i < 3; i++)
{
cin>>p[i].pos>>p[i].maxMove>>p[i].maxThrow;
p[i].lifted = p[i].lifting = p[i].hasMoved = p[i].haslifted = false;
p[i].lift = -1;
pos[p[i].pos] = true;
}
for(int i = 0; i < 9; i++)
{
//合法的第一步,不能为抛出动作
if((i % 3) != 2)
{
vis[i] = true;
dfs(i, 1);
vis[i] = false;
}
}
cout<<ans<<endl;
// stopfile;
return 0;
}