2021圖靈杯 E-nn與遊戲
阿新 • • 發佈:2022-03-13
E.
E-nn與遊戲_第九屆“圖靈杯”NEUQ-ACM程式設計競賽個人賽 (nowcoder.com)
連結:https://ac.nowcoder.com/acm/contest/27302/E
來源:牛客網
先聊聊我對廣搜的認識:以一個點為中心往外擴散,每遇到一個可接受的點,把點的放進佇列,等到下一次使用,以此擴散至邊界。
記錄:用vis陣列記錄,傳值z+1表示步數,若成功則記錄並且點入佇列,不成功則放棄
關於[0,n) 真心覺得c中這個陣列定義下標從零開始真的是煩,有些題目又是從1開始,閉區間,開區間常常會搞錯,綜合考慮我還是接受從1開始的陣列,以後儘量在每一題中體現我的思想。
關於rep,由於我用了 rep和rrep來代替for,經常會被迷惑,還會在題目中巢狀使用,不小心就把i的範圍改了,重新迴圈的時候直接退出。
關於變數名稱的定義,這裡還需要斟酌,有的時候真的會迷惑!!!!!!
思路:
1.記錄:記錄障礙,記錄控制單位和敵對單位。
2.擴散:以控制單位為中心(記錄)x1y1,敵對中心為目標x2y2。
3.佇列: 以pair形式儲存,同時pair又存在map中來標記是否出現
3.函式:用於擴散和增加步數
4.輸出:vis [ x2 ] [ y2 ]-1。
對於步數的記錄:主函式解析,擴散函式中賦值
作用:每次都取上次的步數,防止出現重複計算,以及保證是最小值
#include<bits/stdc++.h> using namespace std; #define fi first #define se second #define pb push_back #define endl '\n' #define debug(x) cout<<"------"<<x<<"-----\n" #define ok() cout<<"YES\n" #define gg() cout<<"NO\n" #define rep(i,a,b) for(int i=a;i<=b;i++) #define rrep(i,a,b) for(int i=a;i>=b;--i) #define IOS ios::sync_with_stdio(false),cin.tie(0); typedef pair <int ,int >PII; typedef vector <int > VI; const int mod = 1e9+7; const int INF =0x3f3f3f3f; const int N=100010; using LL=long long; queue<PII>qe; map<PII,int>ma; int x2,y2,n; int vis[1005][1005]; int bari[1005][1005]; int p[11][5]; void ks(int x,int y,int z) { //找著,且是第一次就找著 if(x==x2&&y==y2&&!vis[x][y]) { vis[x][y]=z; }else if(x<1||x>n||y<1||y>n||vis[x][y]||bari[x][y]||ma.count({x,y})) //滿足邊界,正好踏到了其他點上,遇到了障礙 ,已經找過這個點 { return; }else { vis[x][y]=z; qe.push({x,y}); } } signed main() { int m,t,x,y; cin>>n>>m; rep(i,1,m) { cin>>x>>y; x++;y++; bari[x][y]=-1; //障礙 } cin>>t; rep(i,1,t) { rep(j,1,4) { cin>>p[i][j]; p[i][j]++; } ma[{p[i][1],p[i][2]}]++; ma[{p[i][3],p[i][4]}]++; } rep(k,1,t) { rep(i,1,n) rep(j,1,n) vis[i][j]=0; x=p[k][1];y=p[k][2];x2=p[k][3];y2=p[k][4]; while(!qe.empty()) qe.pop(); qe.push({x,y}); vis[x][y]=1; while(!qe.empty()) { auto f=qe.front(); x=f.fi;y=f.se; qe.pop(); int z=vis[x][y]; ks(x+1,y,z+1); ks(x-1,y,z+1); ks(x,y+1,z+1); ks(x,y-1,z+1); } cout<<vis[x2][y2]-1<<endl; } }