1. 程式人生 > 實用技巧 >AtCoder Beginner Contest 184 ABCDE 題解

AtCoder Beginner Contest 184 ABCDE 題解

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;
}