2020力扣杯团体赛

半退役辣鸡,在打完区域赛之后6个月没训练了,感觉自己就是个弟弟.

1.期望个数统计

就是统计一下不同数字的个数就行了,写个程序暴力算一下会发现同长度的两个全排序的数字相同个数的期望为1.
证明:
其中一位相同的期望为 ( n − 1 ) ! n ! \frac{(n-1)!}{n!} n!(n1)!,共n位,乘一下就是1了

class Solution {
public:
    int expectNumber(vector<int>& scores) {
        sort(scores.begin(),scores.end());
        vector<int> arr(1000010);
        for(int i:scores)
            arr[i]++;
        double ans = 0;
        for(int i=0;i<=1000000;++i)
        {
            if(arr[i])
                ans ++;
        }
        return ans-1;
    }
};

2.小张刷题计划

就是一个常见的二分题
二分一下每天的量,然后暴力算一下是否可行
因为一题不能分几天做,所以天数与每天的量是单调的.
天数多的完成不了的天数少的也肯定完成不了

class Solution {
public:
    int check(vector<int>time,int t)
    {
        int n = time.size(),ans = 0;
        for(int i=0;i<n;++i)
        {
            int mx=-1,need=0,j;
            for(j=i;j<n;++j)
            {
                need+=time[j];
                mx=max(mx,time[j]);
                if(need-mx>t)break;
            }
            ++ans;
            i = j-1;
        }
        //cout<
        return ans;
    }
    
    int minTime(vector<int>& time, int m) {
        int l=0,r=1000000000;
        int ans = (1<<30);
        while(l<=r)
        {
            int mid = l+r>>1;
            if(check(time,mid)<=m)
            {
                r=mid-1;
                ans = min(ans,mid);
            }
            else
                l=mid+1; 
        }
        return ans;
    }
};

3.寻宝

太久没做搜索题了,做了一下人都傻了,想的贼复杂了,估计不是最优的做法,建议到别人博客看一下有没有更好的做法.
我的做法是首先两次bfs算出S到T和O的距离,然后bfs算出各个O到M的距离.然后状压bfs算出答案.因为路肯定是先从S走到O的,然后O到M,M到O,O到M知道走完所有的M.其实也是道常规的搜索题了,主要是平时看见搜索题都直接扔给队友了,现在队友不在了(还活着)做起来就很难受.(冗余代码有点多,写的很丑,见谅)

class Solution {
public:
typedef pair<int,int> P;

vector<string> mp;
int MtoO[20][50];
int OtoM[50][20];
int StoO[50];
int StoT;

int findO[110][110];
int findM[110][110];

struct node
{
    node(){};
    node(int x,int y):x(x),y(y){};
    int x,y;
}O[50],M[20],S,T;
int Mcnt,Ocnt;

int MtoT[20];
bool flag[110][110];

int hx,hy;
int way[8] = {0,-1,0,1,1,0,-1,0};
bool checkStoT;
struct A
{
    A(){};
    A(int x,int y,int dis):x(x),y(y),dis(dis){};
    int x,y,dis;
};
queue<A> que;
void bfsStoT()
{
    while(!que.empty())
        que.pop();
    que.push(A(S.x,S.y,0)); 
    memset(flag,0,sizeof(flag));
    flag[S.x][S.y] = 1;
    while(!que.empty())
    {
        A a = que.front();
        que.pop();
        int x= a.x,y=a.y;
        if(x == T.x && y == T.y)
        {
            checkStoT = 1;
            StoT = a.dis;
        }
        if(mp[x][y] == 'O')
            StoO[findO[x][y]] = a.dis;
        for(int i=0;i<4;++i)
        {
            int nx = x + way[i<<1];
            int ny = y + way[i<<1|1];
            if(nx<0 || ny<0 || nx>= hx || ny >=hy ||flag[nx][ny]||mp[nx][ny]=='#')
                continue;
            flag[nx][ny] = 1;
            que.push(A(nx,ny,a.dis+1));
        }
    }    
}

void bfsMtoO(int i)
{
    while(!que.empty())
        que.pop();
    que.push(A(M[i].x,M[i].y,0));
    memset(flag,0,sizeof(flag));
    flag[M[i].x][M[i].y] = 1;
    while(!que.empty())
    {
        A a = que.front();
        que.pop();
        int x= a.x,y=a.y;
        if(mp[x][y] == 'O')
        {
            MtoO[i][findO[x][y]] = OtoM[findO[x][y]][i] = a.dis;
            //cout<
        }
        if(x==T.x && y==T.y)
        {
            MtoT[i] = a.dis;
        }
        for(int i=0;i<4;++i)
        {
            int nx = x + way[i<<1];
            int ny = y + way[i<<1|1];
            if(nx<0 || ny<0 || nx>= hx || ny >=hy ||flag[nx][ny]||mp[nx][ny]=='#')
                continue;
            flag[nx][ny] = 1;
            que.push(A(nx,ny,a.dis+1));
        }
    }
}
int ans = 0;
//w 0/1 -> M/O
//M 石头 
//O 拿东西
int Mtime[20][100000];
int Otime[50][100000];
bool Mflag[20][100000];
bool Oflag[50][100000];
struct fuck
{
    fuck(){};
    fuck(int id,int zt,int w,int dis):id(id),zt(zt),w(w),dis(dis){};
    int id,zt,w,dis,prezt;
};
queue<fuck> qq;
void dfsans()
{ 
    //cout<
    while(!qq.empty())
        qq.pop();
    memset(Mtime,0x3f,sizeof(Mtime));
    memset(Otime,0x3f,sizeof(Otime));
    memset(Mflag,0,sizeof(Mflag));
    memset(Oflag,0,sizeof(Oflag));
    for(int i=0;i<Ocnt;++i)
    {
        qq.push(fuck(i,0,1,StoO[i]));
        Otime[i][0] = StoO[i];
        Oflag[i][0] = 1;
    }
    while(!qq.empty())
    {
        int id,zt,w,dis;
        fuck f = qq.front();
        qq.pop();
        id = f.id,zt = f.zt,w = f.w;//,dis = Mtime[id][zt];
        if(w==0)
        {
            dis = Mtime[id][zt];
            zt += (1<<id);
            if(zt==(1<<Mcnt)-1)
            {
                if(MtoT[id]!=(1<<30))
                    ans = min(ans,dis+MtoT[id]);
                //cout<
                continue;
            }
            for(int i=0;i<Ocnt;++i)
                if(MtoO[id][i]!=(1<<30))
                {
                    if(dis+MtoO[id][i]<Otime[i][zt])
                        Otime[i][zt] = dis+MtoO[id][i];
                    if(!Oflag[i][zt])
                    {
                        qq.push(fuck(i,zt,1,Mtime[id][zt]+MtoO[id][i]));
                        Oflag[i][zt]=1;
                    }
                }
        }
        else
        {
            dis = Otime[id][zt];
            for(int i=0;i<Mcnt;++i)
            {
                if((zt&(1<<i))) continue;
                if(OtoM[id][i]!=(1<<30))
                {
                    if(dis+OtoM[id][i]<Mtime[i][zt])
                        Mtime[i][zt] = dis+OtoM[id][i];
                    if(!Mflag[i][zt])
                    {
                        qq.push(fuck(i,zt,0,Otime[id][zt]+OtoM[id][i]));
                        Mflag[i][zt] =1;
                    }
                }
            }
        }
    }
}

int minimalSteps(vector<string>& maze)
{
    for(string i:maze)
        mp.push_back(i);
    hx = mp.size();hy = mp[0].length();
    for(int i=0;i<mp.size();++i)
    {
        for(int j=0;j<mp[i].length();++j)
        {
            if(mp[i][j] == 'S')
                S = node(i,j);
            else if(mp[i][j] == 'T')
                T = node(i,j);
            else if(mp[i][j] == 'M')
            {
                findM[i][j] = Mcnt;
                M[Mcnt++] = node(i,j);
            }
            else if(mp[i][j] == 'O')
            {   
                findO[i][j] = Ocnt; 
                O[Ocnt++] = node(i,j);        
            }
        }
    }
    memset(flag,0,sizeof(flag));
    for(int i=0;i<20;++i)
    {
        StoO[i] = MtoT[i] = (1<<30);
        for(int j=0;j<50;++j)
            MtoO[i][j] = OtoM[j][i] = (1<<30);
    }
    checkStoT = 0;
    bfsStoT();
    if(!checkStoT)
        return -1;
    if(Mcnt==0)
        return StoT;
    //cout<<"ok"<
    for(int i=0;i<Mcnt;++i)
    {
        memset(flag,0,sizeof(flag));
        bfsMtoO(i);
    }
    //cout<
    //cout<
    //cout<
    ans = (1<<30);
    dfsans();
    if(ans==(1<<30))
        return -1;
    return ans;
}

};

4. 切分数组

简单dp
dp[i] = min(dp[j-1]+1) (j<=i && gcd(nums[i],nums[j])>=2)
注意一下细节就好了
我的代码写的很暴力,其实可以先算出所有质数再来算.但是复杂度感觉也差不了太多.

class Solution {
public:
int prime[1000010];
int dp[1000010];
int splitArray(vector<int>& nums) 
{
    int e = nums.size();
    int arr[e];
    for(int i=0;i<e;++i)
        arr[i] = nums[i];
    for(int i=0;i<1000010;++i)
        prime[i] = dp[i] = (1<<30);
    int ans = 0;
    for(int i=0;i<e;++i)
    {
        int d = arr[i];
        if(i)
            dp[i] = dp[i-1]+1;
        for(int j = 2;j*j<=d;++j)
        {
            if(d%j==0)
            {
                if(i>0)
                    prime[j] = min(dp[i-1],prime[j]);
                else 
                    prime[j] = 0;
                dp[i] = min(dp[i],prime[j]+1);
                while(d%j==0)
                    d/=j;
            }
        }
        if(nums[i]>1)
        {
            if(i>0)
                prime[d] = min(dp[i-1],prime[d]);
            else
                prime[d] = 0;
            dp[i] = min(dp[i],prime[d]+1);
        }
    }
    return dp[nums.size()-1];
}
};

后面的题还没看,有缘再补吧.

你可能感兴趣的:(acm)