HDU 1650&&3533 【IDA * 和A*】
引子:先说一下IDA* 和A*的内容以及用法。
估价函数:
估价函数假设用h(x)表示,到达目前状态的代价用g(x)表示,那么估计的完成代价为f(x)=g(x)+h(x)。如果f(x)大于题目所需,那么可以进行剪枝。
需要注意的是,h(x)必须小于等于实际最优代价,满足此条件下越接近实际代价该估价函数越优。
A *算法是什么?它是启发式搜索的一种,即广度搜索算法bfs加上估价函数。(八数码||K短路)
而IDA*则是另一种类似的启发式搜索,是迭代加深dfs加上估价函数。
下面两个基础板子题目:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
char mp[9][5];
int n,len[9],pos[9],vis[9],maxlen;
char a[5]="ACGT";
int dfs(int dep)
{
int ma=0;
for(int i=1; i<=n; i++)
{
ma=max(len[i]-pos[i],ma);
}
if(ma==0)
return 1;
if(ma+dep>maxlen)///估值优化
return 0;
int vis[10];
for(int i=0; i<4; i++)
{
memset(vis,0,sizeof vis);
for(int j=1; j<=n; j++)
{
if(mp[j][pos[j]]==a[i])
{
vis[j]=1;
pos[j]++;
}
}
if(dfs(dep+1))
return 1;
for(int j=1; j<=n; j++)///回溯
{
if(vis[j])
{
pos[j]--;
}
}
}
return 0;
}
int main()
{
int t ;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
maxlen=1;
for(int i=1; i<=n; i++)
{
scanf("%s",mp[i]);
len[i]=strlen(mp[i]);
maxlen=max(maxlen,len[i]);
pos[i]=0;
}
while(maxlen)///迭代加深
{
memset(pos,0,sizeof pos);
if(dfs(0))
{
break;
}
maxlen++;
}
printf("%d\n",maxlen);
}
}
#include<bits/stdc++.h>
using namespace std;
int n,m,k,d,odk;
const int maxn=105;
bool mp[maxn][maxn],ok[maxn][maxn][2];
bool vis[105][105][1005];
int dir[4][2]= {
{
0,1},{
0,-1},{
-1,0},{
1,0}};
struct node
{
int t,v,x,y,dir;
} p[maxn],pp[maxn];
struct nod
{
int x,y,step,flag,g,h;
bool operator<(const nod &a)const
{
return a.h<h;
}
};
bool cmp1(node a,node b)
{
if(a.y!=b.y)
return a.y<b.y;
return a.x<b.x;
}
bool cmp2(node a,node b)
{
if(a.x!=b.x)
return a.x<b.x;
return a.y<b.y;
}
priority_queue<nod>q;///优化之后优先队列维护
int bfs()
{
while(!q.empty())q.pop();
q.push({
0,0,0,1});
vis[0][0][0]=1;
while(!q.empty())
{
nod f=q.top(),v;
q.pop();
if(f.step>d)
return 0;
if(f.x==m&&f.y==n)
{
odk=f.step;
return f.step<=d;
}
for(int i=0; i<4; i++)
{
v.x=dir[i][0]+f.x;
v.y=dir[i][1]+f.y;
v.flag=1,v.step=f.step+1,v.g=abs(v.x-n)+abs(v.y-n),v.h=v.step+v.g;///估值优化
if(v.x<0||v.x>m||v.y<0||v.y>n||mp[v.x][v.y]||vis[v.x][v.y][v.step]||ok[v.x][v.y][v.flag])
continue;
vis[v.x][v.y][v.step]=1,ok[v.x][v.y][v.flag]=1;
q.push(v);
}
v=f;
if(f.flag)
{
v.flag=0,v.step=f.step+1,v.g=abs(v.x-n)+abs(v.y-n),v.h=v.step+v.g;
if(v.x<0||v.x>m||v.y<0||v.y>n||mp[v.x][v.y]||vis[v.x][v.y][v.step]||ok[v.x][v.y][v.flag])
continue;
vis[v.x][v.y][v.step]=1,ok[v.x][v.y][v.flag]=1;
q.push(v);
}
}
return 0;
}
int main()
{
while(~scanf("%d%d%d%d",&m,&n,&k,&d))
{
memset(vis,0,sizeof vis);
memset(mp,0,sizeof mp);
memset(ok,0,sizeof ok);
int cnt1=1,cnt2=1;
char c;
for(int i=1; i<=k; i++)
{
cin>>c;
if(c=='N'||c=='S')///N=1,S=2;
{
scanf("%d%d%d%d",&p[cnt1].t,&p[cnt1].v,&p[cnt1].x,&p[cnt1].y);
if(c=='N')
p[cnt1].dir=1;
else
p[cnt1].dir=2;
cnt1++;
}
else///W=3,E=4;
{
scanf("%d%d%d%d",&pp[cnt2].t,&pp[cnt2].v,&pp[cnt2].x,&pp[cnt2].y);
if(c=='W')
pp[cnt2].dir=3;
else
pp[cnt2].dir=4;
cnt2++;
}
}
//cout<<cnt2<<endl;
//
sort(p+1,p+cnt1,cmp1);
sort(pp+1,pp+cnt2,cmp2);
int dir,x,y,t,v;
for(int i=1; i<cnt1; i++)
{
for(int k=1; k<=d; k++)
{
if(k==1)
dir=p[i].dir,x=p[i].x,y=p[i].y,t=p[i].t,v=p[i].v,mp[x][y]=1;
if(p[i].dir==1)
{
x=p[i].x-k*v;
if(x<0||x>n||y<0||y>m||(y==p[i-1].y&&x<=p[i-1].x))
break;
/// cout<<x<<" "<<y<<" "<<k<<endl;
vis[x][y][k]=1;
for(int j=k+t; j<=d; j+=t)
vis[x][y][j]=1;
}
else
{
x=p[i].x+k*v;
if(x<0||x>n||y<0||y>m||(y==p[i+1].y&&x>=p[i+1].x))
break;
/// cout<<x<<" "<<y<<" "<<k<<endl;
vis[x][y][k]=1;
for(int j=k+t; j<=d; j+=t)
vis[x][y][j]=1;
}
}
}
for(int i=1; i<cnt2; i++)
{
for(int k=1; k<=d; k++)
{
if(k==1)
dir=pp[i].dir,x=pp[i].x,y=pp[i].y,t=pp[i].t,v=pp[i].v,mp[x][y]=1;;
if(pp[i].dir==3)
{
y=pp[i].y-k*v;
if(x<0||x>n||y<0||y>m||(x==pp[i-1].x&&y<=pp[i-1].y))
break;
///cout<<x<<"*"<<y<<" "<<k<<endl;
vis[x][y][k]=1;
for(int j=k+t; j<=d; j+=t)
vis[x][y][j]=1;
}
else
{
y=pp[i].y+k*v;
if(x<0||x>n||y<0||y>m||(x==pp[i+1].x&&y>=pp[i+1].y))
break;
/// cout<<x<<" "<<y<<" "<<k<<endl;
vis[x][y][k]=1;
for(int j=k+t; j<=d; j+=t)
vis[x][y][j]=1;
}
}
}
int ans=bfs();
if(ans==0)
puts("Bad luck!");
else
cout<<odk<<endl;
}
}
/*
4 4 3 10
N 1 1 1 1
W 1 1 3 2
W 2 1 2 4
4 4 3 10
N 1 1 1 1
W 1 1 3 2
W 1 1 2 4
*/