HDU - 3533 Escape(预处理+A*)
題目鏈接:點(diǎn)擊查看
題目大意:題意我感覺(jué)描述的很不清楚。。是看網(wǎng)上其他大佬的博客總結(jié)來(lái)的,大意就是我們要從點(diǎn)(0,0)走到點(diǎn)(n,m),然后在一些地方設(shè)置了炮塔(炮塔視為墻),可以向一個(gè)方向周期性地發(fā)射同一速率的炮彈,當(dāng)炮彈到達(dá)某一方格的時(shí)間是整數(shù)時(shí),說(shuō)明當(dāng)我們?cè)谶@個(gè)時(shí)間到達(dá)這個(gè)方格時(shí)會(huì)被擊中,然后我們的行駛路線(xiàn)有五個(gè)方向,分別是上下左右和不動(dòng),并且可以走之前走過(guò)的路,問(wèn)在上述條件下,我們到達(dá)目的地的最短時(shí)間是多少
需要補(bǔ)充一點(diǎn),兩個(gè)炮彈若中途相遇則可以相互穿過(guò),但是炮彈無(wú)法穿過(guò)炮塔
題目分析:我們可以發(fā)現(xiàn)關(guān)于炮塔在某一時(shí)間發(fā)射的炮彈的位置,該方格是無(wú)法供我們行走的,所以我們可以開(kāi)一個(gè)三維的have數(shù)組用來(lái)儲(chǔ)存哪些狀態(tài)是無(wú)法到達(dá)的,預(yù)處理一下,然后再直接bfs深搜即可,注意因?yàn)檫@個(gè)題目中可以回到之前走過(guò)的位置,所以我們可以開(kāi)一個(gè)三維的vis數(shù)組用來(lái)去重,很像之前做過(guò)的動(dòng)態(tài)規(guī)劃+bfs的題目一樣,因?yàn)檫@個(gè)題目的起點(diǎn)和終點(diǎn)都是固定的,我們可以用曼哈頓距離來(lái)比較一下隊(duì)列中的優(yōu)先級(jí),就可以用A*算法優(yōu)化了
上代碼吧:
#include<iostream> #include<string> #include<cstring> #include<cstdio> #include<algorithm> #include<climits> #include<cmath> #include<cctype> #include<stack> #include<queue> #include<list> #include<vector> #include<set> #include<map> #include<unordered_map> using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=110;const int b[5][2]={0,1,0,-1,1,0,-1,0,0,0};bool book[N][N];//儲(chǔ)存炮塔位置bool have[N][N][1100];//儲(chǔ)存炮彈位置bool vis[N][N][1100];//儲(chǔ)存重復(fù)位置int n,m,k,time,ans;struct node//儲(chǔ)存炮彈信息用 {int t,v,x,y,dir; }a[N];bool check(int x,int y)//檢查邊界,注意是從0開(kāi)始到n/m結(jié)束 {if(x<0||y<0||x>n||y>m||book[x][y])return false;return true; }void init()//預(yù)處理炮彈的位置 {for(int i=1;i<=k;i++)//pre{for(int j=0;j<=time;j+=a[i].t)//time{int xx=a[i].x+b[a[i].dir][0];int yy=a[i].y+b[a[i].dir][1];while(check(xx,yy)){int k=abs(xx-a[i].x)+abs(yy-a[i].y);//走了幾步 if(k%a[i].v==0)have[xx][yy][j+k/a[i].v]=true;xx+=b[a[i].dir][0];yy+=b[a[i].dir][1];}}} }struct Node//優(yōu)先隊(duì)列用 {int x,y,time,rtime;Node(int X,int Y,int TIME,int RTIME){x=X;y=Y;time=TIME;rtime=RTIME;}bool operator<(const Node& a)const{return time+rtime>a.time+a.rtime;} };bool A_star() {priority_queue<Node>q;q.push(Node(0,0,0,n+m));vis[0][0][0]=true;while(!q.empty()){Node cur=q.top();q.pop();if(cur.time>time)return false;if(cur.x==n&&cur.y==m){ans=cur.time;return true;}for(int i=0;i<5;i++){int xx=cur.x+b[i][0];int yy=cur.y+b[i][1];int t=cur.time+1;if(!check(xx,yy))continue;if(vis[xx][yy][t])continue;if(have[xx][yy][t])continue;vis[xx][yy][t]=true;int rt=abs(xx-n)+abs(yy-m);q.push(Node(xx,yy,t,rt));}}return false; }int main() {while(scanf("%d%d%d%d",&n,&m,&k,&time)!=EOF){memset(book,false,sizeof(book));memset(have,false,sizeof(have));memset(vis,false,sizeof(vis));for(int i=1;i<=k;i++)//讀入炮彈信息{char dir[5];scanf("%s",dir);if(dir[0]=='E')a[i].dir=0;else if(dir[0]=='W')a[i].dir=1;else if(dir[0]=='S')a[i].dir=2;else if(dir[0]=='N')a[i].dir=3;scanf("%d%d%d%d",&a[i].t,&a[i].v,&a[i].x,&a[i].y);book[a[i].x][a[i].y]=true;}init();if(A_star())printf("%d\n",ans);elseprintf("Bad luck!\n");}return 0; }?
總結(jié)
以上是生活随笔為你收集整理的HDU - 3533 Escape(预处理+A*)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: HDU - 1547 Bubble Sh
- 下一篇: HDU - 4394 Digital S