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 '
'
#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 '
'
#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
",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 '
'
#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;
}


原文地址:https://www.cnblogs.com/Bgwithcode/p/14023868.html