题目:
Little K is interested in BnB mode of the game Crazy Arcade recently. He found it important to preview the exploding time of bombs ,so he worked hard at it. Now, he has another question: How to move to the safe area faster? It takes little K 1 second to move 1 step in four directions, known as up, down, left and right. We can assume that when Little K arrives at a safe area, all bombs in the map explode, and new bombs are generated. And it does not take any time. In another word, when little k find a safe place in this round, he can detonate all the bombs in this round and move to next round. And it does not take any time. Little K has already known the position of bombs in next k rounds. Can you help him to calculate the minimum times to pass through all the explosions safe and sound?
题目大意:
一栋楼有$k$层,每一层大小为$n imes n$,1表示炸弹,0表示安全区,如果走到安全区,可以选择引爆这一层所有的炸弹,如果引爆就进入下一层,并处于上一层的引爆炸弹点的位置,问最少需要走几步,可以将整栋楼炸毁。
分析:
$dp$?。$dp[i][j][k]=$达到第$k$层$(i,j)$这个位子最短需要花多长时间。实际上,我们只需要将每一层的安全区坐标放入一个$vector$里,然后在算到达第$k$层的某一安全区的最短时间,只需枚举$k+1$层上的所有安全区,然后根据状态转移方程$dp[i][j][k]=min(dp[x][y][k+1]+left | i-x ight |+left | j-y ight |)$,就可以算出到达第1层的安全区时间,然后在枚举出发点到第一层所有安全区的步数,取最短步数就可以了。
code:
#define frp #include<bits/stdc++.h> #include <algorithm> #include <cmath> #include <iostream> #include <cstring> #include <string> #include <string.h> #include <iomanip> using namespace std; typedef long long ll; const ll INF = 0x3f3f3f3f; const ll inf = 0x7fffff; const int maxn = 2e6; const int MAXN = 100000 + 5; const int MOD = 1e9 + 7; struct node{ int x,y; }; //放置安全区的坐标 vector<node>m[200]; int dp[200][200][200]; //地图 char mp[200][200][200]; int n,k; void getAns(int sx,int sy){ memset(dp,0x3f, sizeof(dp)); //将第k层的安全区置为0 for(int i=1;i<n+1;i++){ for(int j=1;j<n+1;j++){ if(mp[i][j][k]=='0'){ dp[i][j][k]=0; } } } //从第k-1层开始递推至1层 for(int z=k-1;z>0;z--){ for(int i=0;i<m[z].size();i++){ for(int j=0;j<m[z+1].size();j++){ node iz=m[z][i]; node jz=m[z+1][j]; dp[iz.x][iz.y][z]=min(dp[iz.x][iz.y][z],dp[jz.x][jz.y][z+1]+abs(jz.x-iz.x)+abs(jz.y-iz.y)); } } } int ans=INF; //从第一个层的所有安全区中选取一个到(sx,sy)点总步数最少的 for(int i=0;i<m[1].size();i++){ node tmp=m[1][i]; ans=min(ans,abs(sx-tmp.x)+abs(sy-tmp.y)+dp[tmp.x][tmp.y][1]); } cout<<ans<<endl; } //输入地图,并将安全区放入m中 void getMp(int k,int n){ for(int i=0;i<k;i++){ for(int j=0;j<n;j++){ for(int z=0;z<n;z++){ cin>>mp[j+1][z+1][i+1]; if(mp[j+1][z+1][i+1]=='0'){ m[i+1].push_back({j+1,z+1}); } } } } } //清除m void clear(){ for(int i=0;i<k+1;i++){ m[i].clear(); } } void solve() { int T,sx,sy; cin>>T; while(T--){ cin>>n>>k>>sx>>sy; getMp(k,n); getAns(sx,sy); clear(); } } int main() { ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); #ifdef frp freopen("D:\coding\c_coding\in.txt", "r", stdin); // freopen("D:\coding\c_coding\out.txt", "w", stdout); #endif int t = 1; // cin >> t; while (t--) { solve(); } return 0; }