AtCoder Beginner Contest 184 ABCDE 題解
阿新 • • 發佈:2020-11-23
A - Determinant
簽到。
B - Quizzes
簽到。
C - Super Ryuma
貪心,同時分情況討論:
1.本身就在範圍裡面,就1次(特判起始點和終點重合)。
2.在兩步範圍內(\(|a-c|+|b-d|<=6\)),2次。
3.利用斜線,如果當前不能直接斜線過去,但是通過移動到範圍裡的點再過去,就2次。
4.在終點做一條和我兩條對角線平行的線,交任意一條對角線上於一點,我就可以先移動到這個點再滑過去,2次。此時要看對角線(座標和)奇偶性。交不到點就要3次。
詳見程式碼。
view code
#include<iostream> #include<string> #include<algorithm> #include<cstdio> #include<cstring> #include<cmath> #include<map> #include <queue> #include<sstream> #include <stack> #include <set> #include <bitset> #include<vector> #define FAST ios::sync_with_stdio(false) #define abs(a) ((a)>=0?(a):-(a)) #define sz(x) ((int)(x).size()) #define all(x) (x).begin(),(x).end() #define mem(a,b) memset(a,b,sizeof(a)) #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) #define rep(i,a,n) for(int i=a;i<=n;++i) #define per(i,n,a) for(int i=n;i>=a;--i) #define endl '\n' #define pb push_back #define mp make_pair #define fi first #define se second using namespace std; typedef long long ll; typedef pair<ll,ll> PII; const int maxn = 1e5+200; const int inf=0x3f3f3f3f; const double eps = 1e-7; const double pi=acos(-1.0); const int mod = 1e9+7; inline int lowbit(int x){return x&(-x);} ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d); inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;} inline ll inv(ll x,ll p){return qpow(x,p-2,p);} inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;} inline ll read(){ ll f = 1; ll x = 0;char ch = getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0', ch = getchar();return x*f; } int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} }; int main() { ll a = read(), b = read(), c = read(), d = read(); if(a==c&&b==d) { cout<<0<<endl; } else if(a+b==c+d||a-b==c-d||abs(a-c)+abs(b-d)<=3) { cout<<1<<endl; } else { if(abs(a-c)+abs(b-d)<=6) cout<<2<<endl; // 兩步方框距離 else { int flag = 0; for(int i=a-3; i<= a+3; i++) for(int j=b-3; j<=b+3; j++) //找方框裡面能否有直接斜線到終點的 { if(abs(i-a)+abs(j-b) <= 3&&i+j==c+d||i-j==c-d) flag = 1; } if(flag) cout<<2<<endl; //有就萬幸 else //無的話 { if(((a+b)&1LL)==((c+d)&1LL)) cout<<2<<endl; //看對角線奇偶性 else cout<<3<<endl; } } } return 0; }
D - increment of coins
題意:一開始有三種顏色的石子分別為A,B,C個。一次可以隨機拿出一個石子,放回兩個同顏色的。問把全部都替換成100個同色的需要的步數的期望。
思路:當前一個狀態,如(97,98,99),往下有三個子狀態:
1.(98,98,99)
2.(97,99,99)
3.(97,98,100)
同理這三個子狀態往下也有三個狀態,直到有一位到100。那麼根據期望的定義,我們就知道當前的期望是三種可能需要的步數乘上對應概率,然後加和。
而這三種可能(子狀態)所需要的步數又是他們各自的期望,這就分解了子問題,用DP求解即可。這裡採用記憶化搜尋。
view code
#include<iostream> #include<string> #include<algorithm> #include<cstdio> #include<cstring> #include<cmath> #include<map> #include <queue> #include<sstream> #include <stack> #include <set> #include <bitset> #include<vector> #define FAST ios::sync_with_stdio(false) #define abs(a) ((a)>=0?(a):-(a)) #define sz(x) ((int)(x).size()) #define all(x) (x).begin(),(x).end() #define mem(a,b) memset(a,b,sizeof(a)) #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) #define rep(i,a,n) for(int i=a;i<=n;++i) #define per(i,n,a) for(int i=n;i>=a;--i) #define endl '\n' #define pb push_back #define mp make_pair #define fi first #define se second using namespace std; typedef long long ll; typedef pair<ll,ll> PII; const int maxn = 1e5+200; const int inf=0x3f3f3f3f; const double eps = 1e-7; const double pi=acos(-1.0); const int mod = 1e9+7; inline int lowbit(int x){return x&(-x);} ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d); inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;} inline ll inv(ll x,ll p){return qpow(x,p-2,p);} inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;} inline ll read(){ ll f = 1; ll x = 0;char ch = getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0', ch = getchar();return x*f; } int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} }; double dp[105][105][105]; double DP(int A, int B , int C) { if(A>=100||B>=100||C>=100) return 0; if(dp[A][B][C] != -1) return dp[A][B][C]; dp[A][B][C] = ((DP(A+1,B,C)+1)*A/(double)(A+B+C))+((DP(A,B+1,C)+1)*B/(double)(A+B+C))+((DP(A,B,C+1)+1)*C/(double)(A+B+C)); return dp[A][B][C]; } int main() { rep(i,0,101) rep(j,0,101) rep(k,0,101) dp[i][j][k] = -1 ; double a, b, c; cin>>a>>b>>c; printf("%.6lf\n",DP(a,b,c)); return 0; }
E - Third Avenue
經典BFS問題,在走迷宮的問題上加了傳送而已。我們先用map記錄每個字母有哪些傳送口,然後第一次遇到這個字母的時候,不但可以四方向走,而且還可以將傳送位置丟進佇列。有一點要注意的是,我第一次遇到這個字母的時候把能走的相同字母都傳送過去,下次再遇到這個字母就沒必要再看傳送了,因為肯定不是最優(走老路),這樣就將時間複雜度也降下來了O(26nm)。具體實現見程式碼。
view code
#include<iostream> #include<string> #include<algorithm> #include<cstdio> #include <string.h> #include <stdio.h> #include <unordered_map> #include<cstring> #include<cmath> #include<map> #include <queue> #include<sstream> #include <stack> #include <set> #include <bitset> #include<vector> #define FAST ios::sync_with_stdio(false) #define abs(a) ((a)>=0?(a):-(a)) #define sz(x) ((int)(x).size()) #define all(x) (x).begin(),(x).end() #define mem(a,b) memset(a,b,sizeof(a)) #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) #define rep(i,a,n) for(int i=a;i<=n;++i) #define per(i,n,a) for(int i=n;i>=a;--i) #define endl '\n' #define pb push_back #define mp make_pair #define fi first #define se second using namespace std; typedef long long ll; typedef pair<ll,ll> PII; const int maxn = 1e5+200; const int inf=0x3f3f3f3f; const double eps = 1e-7; const double pi=acos(-1.0); const int mod = 1e9+7; inline int lowbit(int x){return x&(-x);} ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d); inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;} inline ll inv(ll x,ll p){return qpow(x,p-2,p);} inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;} inline int read(){ int f = 1; int x = 0;char ch = getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0', ch = getchar();return x*f; } int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} }; char s[3000][3000]; int n, m; int vis[3000][3000]; int d[3000][3000]; int path[30]; unordered_map<int, vector<PII> > to; int Sx,Sy, Gx,Gy; bool check(int x, int y) { if(x>n||x<1||y>m||y<1||vis[x][y]||s[x][y]=='#') return false; return true; } ll bfs() { queue<PII> q; d[Sx][Sy] = 0; vis[Sx][Sy] = 1; q.push(mp(Sx,Sy)); while(!q.empty()) { int x = q.front().fi; int y = q.front().se; q.pop(); if(s[x][y] == 'G') return d[x][y]; rep(i,0,3) { int xx = x + dir[i][0]; int yy = y + dir[i][1]; if(check(xx,yy)&&!vis[xx][yy]) { vis[xx][yy] = 1; d[xx][yy] = d[x][y] + 1; q.push(mp(xx,yy)); } } if(s[x][y]>='a'&&s[x][y]<='z'&&!path[s[x][y]-'a']) { path[s[x][y]-'a'] = 1; for(int i=0; i<to[s[x][y]-'a'].size(); i++) { int tox = to[s[x][y]-'a'][i].fi; int toy = to[s[x][y]-'a'][i].se; if(check(tox,toy)&&!vis[tox][toy]&&!(tox==x&&toy==y)) { vis[tox][toy] = 1; d[tox][toy] = d[x][y] + 1; q.push(mp(tox,toy)); } } } } return -1; } int main() { cin>>n>>m; char ch = getchar(); rep(i,1,n) scanf("%s",s[i]+1); rep(i,1,n) rep(j,1,m) { if(s[i][j] == 'S') Sx = i, Sy = j; else if(s[i][j]=='G') Gx = i, Gy = j; else if(s[i][j]>='a'&&s[i][j]<='z') to[s[i][j]-'a'].pb(mp(i,j)); } ll ans = bfs(); cout<<ans<<endl; return 0; }