2020牛客寒假算法基础集训营3

B.牛牛的DRB迷宫II

题解

看到构造题就傻眼了,当时脑子一直在想组合数的方法.....
事后问了学长,由于这是一个方案叠加,所以我们通过拆二进制的方法来解决这个问题
1 1 1 1
1 1 1 2
1 1 2 4
1 2 4 8
这个就是我们构造的2的幂的解。那么剩下的呢,举个例子吧,比如是11
1 1 1 1 1
1 1 1 2 3
1 1 2 4 3
1 2 4 8 11
因为语言难以描述,所以我就不描述了
学长说构造题拆二进制是常见思路,那我就先记下吧

#include<bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
typedef long long LL;
typedef pair<int,int> PII;
#define X first
#define Y second
inline int read()
{
    int x=0,f=1;char c=getchar();
    while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
    while(isdigit(c)){x=x*10+c-'0';c=getchar();}
    return x*f;
}
int x,len=1,dp[50][50],i,j,k;
char a[52][52];
int main()
{
    x=read();
    if(!x)x=1000000007;
    for(i=31;i>=0;i--)if(x>>i)break;
    printf("%d %d\n",i+1,i+2);
    for(j=0;j<i+1;j++)for(k=0;k<i+2;k++)a[j][k]='B';
    for(k=0;k<i+2;k++)a[i][k]='R';
    for(j=1;j<i;j++)for(k=0;k<i-j;k++)a[j][k]='D';
    for(j=0;j<=i;j++)a[j][i+1]='D';
    for(j=0;j<i;j++)if(x>>j&1)a[j][i]='B';else a[j][i]='D';
    for(j=0;j<i+1;j++)printf("%s\n",a[j]);
    return 0;
}

E.牛牛的随机数

题解

根据套路肯定是算每个二进制位对答案的贡献,那么我们只需要求一个函数\(f(x,i)\) 表示在\([1,x]\) 区间内二进制位\(i\) 出现了多少次1,然后将贡献叠加即可。
(这个所谓的函数虽然就几行,但是好难写)

J.牛牛的宝可梦Go

题解

我开始想了一个\(O(m*n^2)\) 的做法,是设\(dp[i][j]\) 表示当前在\(i\) 时间,在\(j\) 城市的最大值,但是转移是\(O(n)\) 的,所以不行
换一个思路\(DP\)\(dp[i]\) 表示当前捕捉了神奇宝贝\(i\) 的最大价值,转移的话就从最近200个开始转移,因为200个以外的,都距离超过200个时间了,必能走到、
细节1:图可能不联通(这个意识到了)
细节2:\(dp\) 数组应该先设为\(-oo\) ,要不然有可能从不合法的地方继承过来(死于此)

#include<bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
typedef long long LL;
typedef pair<int,int> PII;
#define X first
#define Y second
inline int read()
{
    int x=0,f=1;char c=getchar();
    while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
    while(isdigit(c)){x=x*10+c-'0';c=getchar();}
    return x*f;
}
const int maxn=210,maxm=100010;
int n,m,u,v,w,tot,dis[maxn][maxn];
LL dp[maxm],ans;//dp[i][j]表示当前在i城市,j时间的最大值 
struct Pokemon
{
    int t,p,val;
    Pokemon() {}
    Pokemon(int _1,int _2,int _3):t(_1),p(_2),val(_3) {}
    bool operator < (const Pokemon &s)const {return t<s.t;}
}a[maxm];
int main()
{
    mem(dis,42);
    n=read();m=read();
    while(m--)u=read(),v=read(),dis[u][v]=dis[v][u]=1;
    for(int i=1;i<=n;i++)dis[i][i]=0;
    for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
    m=read();
    for(int i=1;i<=m;i++)
    {
        u=read(),v=read(),w=read();
        if(dis[1][v]>500)continue;
        a[++tot]=Pokemon(u,v,w);
    }
    m=tot;
    sort(a+1,a+m+1);
    a[0].p=1;
    for(int i=1;i<=m;i++)dp[i]=-1ll<<60;
    for(int i=1;i<=m;i++) 
        for(int j=i-1;j>=max(0,i-500);j--)
            if(dis[a[i].p][a[j].p]<=a[i].t-a[j].t)dp[i]=max(dp[i],dp[j]+a[i].val);
    for(int i=0;i<=m;i++)ans=max(ans,dp[i]);
    printf("%lld\n",ans);
    return 0;
}

废话

细节杀我

猜你喜欢

转载自www.cnblogs.com/FYH-SSGSS/p/12285373.html