zoukankan      html  css  js  c++  java
  • [USACO 2017 Jan Gold] Tutorial

    Link:

    传送门

    A:

    按值大小插入后用树状数组统计两边个数

    #include <bits/stdc++.h>
    
    using namespace std;
    #define X first
    #define Y second
    #define pb push_back
    typedef double db;
    typedef long long ll;
    typedef pair<int,int> P;
    const int MAXN=1e5+10;
    P dat[MAXN];
    int n,bit[MAXN],dsp[MAXN],l[MAXN],r[MAXN],res,tot;
    
    void Update(int x)
    {while(x<=n) bit[x]++,x+=x&(-x);}
    int Query(int x)
    {
        int ret=0;
        while(x) ret+=bit[x],x-=x&(-x);
        return ret;
    }
    
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) 
            scanf("%d",&dat[i].X),dsp[++tot]=dat[i].X,dat[i].Y=i;
        sort(dsp+1,dsp+n+1);tot=unique(dsp+1,dsp+n+1)-dsp-1;
        for(int i=1;i<=n;i++)
            dat[i].X=lower_bound(dsp+1,dsp+tot+1,dat[i].X)-dsp;
        sort(dat+1,dat+n+1,greater<P>());
        
        for(int i=1;i<=n;i++)
        {
            l[i]=Query(dat[i].Y-1);
            r[i]=i-1-l[i];Update(dat[i].Y);
            if(max(l[i],r[i])>min(l[i],r[i])*2) res++;
        }
        printf("%d",res);
        return 0;
    }
    Problem A

    B:

    $dp[i][j][k]$表示前$i$项换$j$次末状态为$k$的最优解

    每次分换或不换转移即可

    #include <bits/stdc++.h>
    
    using namespace std;
    #define X first
    #define Y second
    #define pb push_back
    typedef double db;
    typedef long long ll;
    typedef pair<int,int> P;
    const int MAXN=1e5+10;
    char s[10];int res=0;
    int n,m,dat[MAXN],dp[MAXN][25][5];
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%s",s+1);
            if(s[1]=='H') dat[i]=0;
            else if(s[1]=='P') dat[i]=1;
            else dat[i]=2;
        }
        dp[1][0][dat[1]]=1;
        for(int i=1;i<n;i++)
            for(int j=0;j<=m;j++)
                for(int k=0;k<3;k++)
                {
                    dp[i+1][j][k]=max(dp[i+1][j][k],dp[i][j][k]+(k==dat[i+1]));
                    for(int l=0;l<3;l++)
                        if(l!=k) dp[i+1][j+1][l]=max(dp[i+1][j+1][l],dp[i][j][k]+(l==dat[i+1]));
                }
        for(int i=0;i<=m;i++)
            for(int j=0;j<3;j++)
                res=max(res,dp[n][i][j]);
        printf("%d",res);
        return 0;
    }
    Problem B

    C:

    一开始看到数据范围$n<20$感觉就是暴力……

    最后发现用一个6维数组记录当前两点位置和朝向$bfs$就行了……

    注意:

    1、一个点到终点后就不再移动了!

    2、学会用函数返回引用来简化代码,这样就不用每次写6维的数了……

    #include <bits/stdc++.h>
    
    using namespace std;
    #define X first
    #define Y second
    #define pb push_back
    typedef double db;
    typedef long long ll;
    typedef pair<int,int> P;
    const int MAXN=25;
    char s[MAXN];
    struct node{int x1,y1,d1,x2,y2,d2;};
    queue<node> q;int res=1<<30;
    int n,dat[MAXN][MAXN],d[25][25][4][25][25][4];
    
    int dx[]={-1,0,1,0};
    int dy[]={0,1,0,-1};
    
    int nxt(int x){return (x+1)%4;}
    int pre(int x){return (x+3)%4;}
    void update(node x,node y)
    {
        int &a=d[x.x1][x.y1][x.d1][x.x2][x.y2][x.d2];
        int &b=d[y.x1][y.y1][y.d1][y.x2][y.y2][y.d2];
        if(a>b+1) a=b+1,q.push(x);
    }
    
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%s",s+1);
            for(int j=1;j<=n;j++)
                dat[i][j]=(s[j]=='E');
        }
        memset(d,0x3f,sizeof(d));
        //注意一个点到终点后就不动了 
        d[n][1][0][n][1][1]=0;
        q.push((node){n,1,0,n,1,1});
        while(!q.empty())
        {
            node t=q.front();q.pop();
            node a=t,b=t,c=t;
            if(!(t.x1==1&&t.y1==n)) a.d1=nxt(a.d1),b.d1=pre(b.d1);
            if(!(t.x2==1&&t.y2==n)) a.d2=nxt(a.d2),b.d2=pre(b.d2);
            
            update(a,t);update(b,t);
            
            int fx1=c.x1+dx[c.d1],fx2=c.x2+dx[c.d2];
            int fy1=c.y1+dy[c.d1],fy2=c.y2+dy[c.d2];
            if(fx1>=1&&fy1<=n&&dat[fx1][fy1]&&!(c.x1==1&&c.y1==n)) c.x1=fx1,c.y1=fy1;
            if(fx2>=1&&fy2<=n&&dat[fx2][fy2]&&!(c.x2==1&&c.y2==n)) c.x2=fx2,c.y2=fy2;
            update(c,t);
        }
        
        for(int i=0;i<4;i++)
            for(int j=0;j<4;j++)
                res=min(res,d[1][n][i][1][n][j]);
        printf("%d",res);
        return 0;
    }
    Problem C
  • 相关阅读:
    AIoT 2020 年分析
    TensorFlow解析常量、变量和占位符
    TensorFlow编程结构
    对端边缘云网络计算模式:透明计算、移动边缘计算、雾计算和Cloudlet
    Harmony生命周期
    立体显示与BCN双稳态手性向列相
    显示技术示例
    SystemML大规模机器学习,优化算子融合方案的研究
    改天有空看看 1
    gradle 123123
  • 原文地址:https://www.cnblogs.com/newera/p/9637699.html
Copyright © 2011-2022 走看看