#include<bits/stdc++.h>
using namespace std;
struct DP{
int zan[6000000],gs[6000000];
int top;
}dp[2];
int n,m,a,b;
int dt[15][15];
int HASH[8000000];//不会用哈希 QaQ
int ans_MAX,ans_MIN;
int fx[5]={0,0,0,1,-1};
int fy[5]={0,1,-1,0,0};
bool check(int x){//检查 x 是否在范围内
if(x<1||x>n)return 0;
return 1;
}
int maxx(int x,int y){//MAX
return x>y? x:y;
}
void read(){//读入
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
dt[i][j]=1;
}
}
for(int i=1;i<=m;i++){
scanf("%d%d",&a,&b);
dt[n-a+1][b]=0;
}
ans_MAX=0;
ans_MIN=0;
}
void bfs(){//普通的 BFS
ans_MIN=0;
int dl[250][2],l=1,r=1;
dl[r][0]=1,dl[r][1]=1;
int pd[15][15];
memset(pd,0,sizeof(pd));
pd[1][1]=1;
while(l<=r){
int jr=r;
for(int i=l;i<=jr;i++){
int x=dl[i][0],y=dl[i][1];
for(int j=1;j<=4;j++){
int xx=x+fx[j],yy=y+fy[j];
if(dt[xx][yy]&&!pd[xx][yy]&&check(xx)&&check(yy))r++,dl[r][0]=xx,dl[r][1]=yy,pd[xx][yy]=1;
}
}
l=jr+1;ans_MIN++;
if(pd[n][n])return ;
}
ans_MIN=-1;
}
void csh(){//初始化
dp[1].top=0;
dp[0].top=2;
dp[0].zan[1]=(1<<(n<<1));
dp[0].gs[1]=1;
dp[0].zan[2]=(1<<((n-1)<<1));
dp[0].gs[2]=1;
}
void add(int k,int gs,int y){//加入状态
if(y==n){//行末特判
if(k&3)return ;
k>>=2;
}
int zz=HASH[k];
if(!zz){
dp[1].top++;
zz=HASH[k]=dp[1].top;
dp[1].zan[zz]=k;
dp[1].gs[zz]=gs;
}
else{
dp[1].gs[zz]=maxx(dp[1].gs[zz],gs);
}
}
void gb(int &k,int pd,int st){//改变不合法括号
int jy[20],kk=k;
int top=0;
for(int i=n+1;i>0;i--){//解压
jy[i]=(kk&3);
kk>>=2;
}
if(pd==1){//栈
for(int i=st+2;i<=n+1;i++){
if(jy[i]==1)top++;
else if(jy[i]==2){
if(top)top--;
else{
k-=(1<<((n-i+1)<<1));
return ;
}
}
}
}
else{//栈
for(int i=st-1;i>0;i--){
if(jy[i]==2)top++;
else if(jy[i]==1){
if(top)top--;
else{
k+=(1<<((n-i+1)<<1));
return ;
}
}
}
}
}
void js(int x,int y){//计算
int left=3<<((n+1-y)<<1),up=left>>2;
while(dp[0].top){
int k=dp[0].zan[dp[0].top],gs=dp[0].gs[dp[0].top];dp[0].top--;//取出
int ztu=(k&up),ztl=(k&left);
k=k-ztu-ztl;//将 下,右 插头 清零
ztl>>=((n+1-y)<<1);//将状态转化为 1,2 (方便检查)
ztu>>=((n-y)<<1);
if(!(ztu|ztl)){//没有插头
add(k,gs,y);//不走 空着
if(dt[x][y])
add(k|(up<<1),gs+1,y);//空地可以走
}
else if(!dt[x][y])continue;//有插头并且是障碍不合法
else if(ztu>0&&ztl>0){//有两个插头
if(ztu==ztl){//相同
int kk=k;
gb(kk,ztu,y);//改变不合法插头
add(kk,gs+1,y);// 走
}
else if(ztu==1){
add(k,gs+1,y);// up 为 1 时合法
}
else continue; // up 为 2 时不合法
}
else{
int ad=(ztu|ztl);//只有一个插头
add(k|(ad<<((n-y)<<1)),gs+1,y);//两种出法
add(k|(ad<<((n+1-y)<<1)),gs+1,y);
}
}
dp[0]=dp[1];
while(dp[1].top)HASH[dp[1].zan[dp[1].top--]]=0;//清空 数组
}
void CT(){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i==1&&j==1)continue;//第一个点初始化过了
if(i==n&&j==n)return ;//最后一个点,也就是终点不用计算
js(i,j);
}
}
}
void dq(){//读取 读取答案 ans_MAX
for(int i=1;i<=dp[0].top;i++){
if(dp[0].zan[i]==1||dp[0].zan[i]==4)ans_MAX=maxx(ans_MAX,dp[0].gs[i]);
}
}
void ZY_DP(){//装压DP
csh(); // 初始化
CT(); // 插头DP CT
dq();// 读取
}
int main(){
read();//输入
bfs();//最短路
ZY_DP();//最长路
cout<<ans_MAX-ans_MIN<<endl;//时差
}
P1117 [NOI2016] 优秀的拆分
最新推荐文章于 2024-09-13 16:27:15 发布
本文介绍了一种使用C++编程实现的算法,结合BFS和自定义的数据结构DP,以及哈希技术,解决了一个关于在给定网格中找到从起点到终点的最短路径和最长路径时差的问题。算法首先进行最短路径搜索,然后使用CSh和状态转移优化求解最长路径。
摘要由CSDN通过智能技术生成