POJ 2331 Water pipe IDA*

预处理估价函数。其他的套模板就可以了。

不过有一个地方没住意WA了2小时。

#include<stdio.h> #include<string.h> #include<queue> using namespace std; int sx,sy,tx,ty,n; int len[5],num[5]; int bound,total; int h[2]={1,-1}; int hx[1010],hy[1010]; bool ans; struct point{ int x; int step; }; int Min(int a,int b){ return a>b?b:a; } void bfs(int v,int * hx){ int i,j,u,xx; queue<struct point>que; struct point sta; sta.step=0; sta.x=v; que.push(sta); hx[v]=0; while(!que.empty()){ struct point tem; tem=que.front(); que.pop(); u=tem.x; for(i=0;i<2;i++){ for(j=1;j<=n;j++){ xx=u+len[j]*h[i]; if(xx<=0 || xx>1000 || hx[xx]!=-1) continue; if(hx[u]+1>total) continue; hx[xx]=hx[u]+1; struct point cur; cur.step=hx[xx]; cur.x=xx; que.push(cur); } } } } int dfs(int dep,int x,int *nu,int type){ int i,j,xx,next_bound; if(type==0){ if(dep+hx[x]+hy[sy]>bound) return dep+hx[x]+hy[sy]; if(hx[x]==0) return dfs(dep,sy,nu,1); } else if(type==1){ if(dep+hy[x]>bound) return dep+hy[x]; if(hy[x]==0){ ans=true; return dep; } } int tmp[5]; for(i=1;i<=n;i++) tmp[i]= nu[i]; int new_bound=1e7; for(i=0;i<2;i++){ for(j=1;j<=n;j++) if(tmp[j]){ tmp[j]--; xx=x+h[i]*len[j]; if(xx<=0 || xx>1000 ){ tmp[j]++; //一开始我这里忘了去恢复现场,WA了好久 continue; } if(type==0){ if(hx[xx]==-1){ tmp[j]++; continue; //一开始我这里忘了去恢复现场,WA了好久 } } if(type==1){ if(hy[xx]==-1){ tmp[j]++; continue; //一开始我这里忘了去恢复现场,WA了好久 } } next_bound = dfs(dep+1,xx,tmp,type); if(!ans) new_bound=Min(new_bound,next_bound); else return next_bound; tmp[j]++; } } return new_bound; } void IDA_STAR(){ memset(hx,-1,sizeof(hx)); memset(hy,-1,sizeof(hy)); bfs(tx,hx); bfs(ty,hy); if(hx[sx]==-1 || hy[sy]==-1){ printf("-1\n"); return; } bound=hx[sx]+hy[sy]; while(bound<=total && !ans){ bound=dfs(0,sx,num,0); } if(ans) printf("%d\n",bound); else printf("-1\n"); } int main(){ int i,j; scanf("%d%d%d%d",&sx,&sy,&tx,&ty); scanf("%d",&n); for(i=1;i<=n;i++) scanf("%d",&len[i]); total=0; for(i=1;i<=n;i++){ scanf("%d",&num[i]); total+=num[i]; } ans=false; IDA_STAR(); }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值