zoukankan      html  css  js  c++  java
  • 2020 年百度之星·程序设计大赛

    Problem A

    模拟即可

    Problem B

    由题可知每一个点都在以一个点为圆心,固定距离为半径的圆周上运动,那么要距离最小,直觉告诉我们是在同一条直线上,且位于同侧,但是看数据量发现,直接计算会炸时间,那么我们可以看看,一个距离在总和中有多少贡献,然后公式计算一下,可以优化到常数的时间复杂度。

    Problem C

    模拟就可以了,我们遍历每一个时间点,然后看在这个时间点的时候和现在感染的人在同一个位置的人,标记它,并且把这个点给pop出当前的轨迹。

    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<map>
    #include<iostream>
    #include<cstring>
    #include<cmath>
    using namespace std;
    #define rep(i,f_start,f_end) for (int i=f_start;i<=f_end;++i)
    #define per(i,n,a) for (int i=n;i>=a;i--)
    #define MT(x,i) memset(x,i,sizeof(x) )
    #define rev(i,start,end) for (int i=start;i<end;i++)
    #define inf 0x3f3f3f3f
    #define mp(x,y) make_pair(x,y)
    #define lowbit(x) (x&-x)
    #define MOD 1000000007
    #define exp 1e-8
    #define N 1000005 
    #define fi first 
    #define se second
    #define pb push_back
    typedef long long ll;
    const ll INF=0x3f3f3f3f3f3f3f3f;
    typedef vector <int> VI;
    typedef pair<int ,int> PII;
    typedef pair<int ,PII> PIII;
    ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
    ll lcm(ll a,ll b){return a/gcd(a,b)*b;};
    void check_max (int &a,int b) { a=max (a,b);}
    void check_min (int &a,int b) { a=min (a,b);}
    int tt;
    
    int main () {
        scanf ("%d",&tt);
        while (tt--) {
            int n;
            scanf ("%d",&n);
            vector <queue <PII>> people (n);
            int time=0;
            for (int len,t,p,i=0;i<n;i++) {
                scanf ("%d",&len);
                rep (j,1,len) {
                    scanf ("%d%d",&t,&p);
                    people[i].push ({t,p});
                    time=max (time,t);
                }           
            }
            vector <bool> sign (n,0);
            int pos[12]={0};
            sign[0]=true;
            rep (i,1,time) {
                rev (j,0,n) {
                    if (sign[j]&&people[j].size ()&&people[j].front().first==i)
                       pos[people[j].front().second]=i;
                }
                rev (j,0,n) {
                    if (people[j].size ()&&people[j].front().first==i) {
                        if (pos[people[j].front().second]==i) sign[j]=true;
                        people[j].pop ();
                    }
                   
                }
            }
            printf ("1");
            rep (i,2,n) if (sign[i-1]) printf (" %d",i);
            printf ("
    ");
        }
        return 0;
    }
    

    Problem D

    爆搜是赛后提交会超时,标程是二分?

    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<map>
    #include<iostream>
    #include<cstring>
    #include<cmath>
    using namespace std;
    #define rep(i,f_start,f_end) for (int i=f_start;i<=f_end;++i)
    #define per(i,n,a) for (int i=n;i>=a;i--)
    #define MT(x,i) memset(x,i,sizeof(x) )
    #define rev(i,start,end) for (int i=start;i<end;i++)
    #define inf 0x3f3f3f3f
    #define mp(x,y) make_pair(x,y)
    #define lowbit(x) (x&-x)
    #define MOD 1000000007
    #define exp 1e-8
    #define N 1000005 
    #define fi first 
    #define se second
    #define pb push_back
    typedef long long ll;
    const ll INF=0x3f3f3f3f3f3f3f3f;
    typedef vector <int> VI;
    typedef pair<int ,int> PII;
    typedef pair<int ,PII> PIII;
    ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
    ll lcm(ll a,ll b){return a/gcd(a,b)*b;};
    void check_max (int &a,int b) { a=max (a,b);}
    void check_min (int &a,int b) { a=min (a,b);}
    string str;
    int t,n;
    map <int,int> mp;
    
    void dfs (int cnt,int &ans,int sum[]) {
        if (cnt==10) {
            int k=inf;
            rev (i,0,5)  k=min (k,sum[i]);
            ans=min (ans,n-k);
            return ;
        }
        rev (i,0,5) {
            sum[i]+=mp[cnt];
            dfs (cnt+1,ans,sum);
            sum[i]-=mp[cnt];
        }
    }
    
    int main () {
        ios::sync_with_stdio (false);
        cin>>t;
        while (t--) {
          mp.clear ();
          cin>>n;
          rep (i,1,n) {
              cin>>str;
              mp[str.back ()-'0']++;
          }
          int ans=inf;
          int sum[5]={0};
          dfs (0,ans,sum);
          cout<<ans<<endl;
        }
        return 0;
    }
    

    Problem E

    最小费用最大流,我们可以发现一共就只有六种情况,所以我们把这六种情况压成点,然后圆点出发连三种饮料,cap是数量,然后发别连向每种情况,并加上对于的费用,然后每种情况连接到汇点,cap是情况的个数

    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<map>
    #include<iostream>
    #include<cstring>
    #include<cmath>
    using namespace std;
    #define rep(i,f_start,f_end) for (int i=f_start;i<=f_end;++i)
    #define per(i,n,a) for (int i=n;i>=a;i--)
    #define MT(x,i) memset(x,i,sizeof(x) )
    #define rev(i,start,end) for (int i=start;i<end;i++)
    #define inf 0x3f3f3f3f
    #define mp(x,y) make_pair(x,y)
    #define lowbit(x) (x&-x)
    #define MOD 1000000007
    #define exp 1e-8
    #define N 1000005 
    #define fi first 
    #define se second
    #define pb push_back
    typedef long long ll;
    const int INF=0x3f3f3f3f;
    typedef vector <int> VI;
    typedef pair<int ,int> PII;
    typedef pair<int ,PII> PIII;
    ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
    ll lcm(ll a,ll b){return a/gcd(a,b)*b;};
    void check_max (int &a,int b) { a=max (a,b);}
    void check_min (int &a,int b) { a=min (a,b);}
    const int maxn=5e4+10;
    const int M=5e3+10;
    int n,m,s,t,cnt=1,tt;
    int head[maxn],dis[maxn],pre[maxn],incf[maxn];
    int maxflow,mincost;
    bool vis[maxn];
    struct edge {
        int v,next,flow,cost;
    }e[M<<1];
    
    inline void add (int u,int v,int flow,int cost) {
        e[++cnt]= (edge) {v,head[u],flow,cost};
        head[u]=cnt;
    }
    
    inline void add_edge (int u,int v,int flow,int cost) {
       add (u,v,flow,cost);
       add (v,u,0,-cost);
    }
    
    inline bool spfa () {
        queue <int > q;
        MT (dis,0x3f);
        MT (vis,0);
        q.push (s);
        dis[s]=0;
        vis[s]=1;
        incf[s]=1<<30;
        while (q.size ()) {
            int x=q.front (); q.pop ();
            vis[x]=0;
            for (int i=head[x];i;i=e[i].next) {
               if (!e[i].flow) continue;
               int v=e[i].v;
               if (dis[v]>dis[x]+e[i].cost) {
                   dis[v]=dis[x]+e[i].cost;
                   incf[v]=min (incf[x],e[i].flow);
                   pre[v]=i;
                   if (!vis[v]) vis[v]=1,q.push (v);
               }
            }
        }
        if (dis[t]==inf) return 0;
        return dis[t];
    }
    
    inline void mcmf () {
        while (spfa ()) {
           int x=t;
           maxflow+=incf[t];
           mincost+=dis[t]*incf[t];
           int i;
           while (x!=s) {
               i=pre[x];
               e[i].flow-=incf[t];
               e[i^1].flow+=incf[t];
               x=e[i^1].v;
           }
        }
    }
    int main () {
        scanf ("%d",&tt);
        while (tt--) {
            MT (head,0);
            cnt=1; maxflow=0,mincost=0;
            int n,a,b,c;
            scanf ("%d%d%d%d",&n,&a,&b,&c);
            char str[4];
            vector <int> v(6);
            s=0,t=10;
            rep (i,1,n) {
                scanf ("%s",&str);
                if (strcmp (str,"012")==0) v[0]++;
                if (strcmp (str,"021")==0) v[1]++;
                if (strcmp (str,"102")==0) v[2]++;
                if (strcmp (str,"210")==0) v[3]++;
                if (strcmp (str,"201")==0) v[4]++;
                if (strcmp (str,"120")==0) v[5]++;
            }
    
                add_edge (s,1,a,0);
                add_edge (s,2,b,0);
                add_edge (s,3,c,0);
    
                add_edge (1,4,INF,-3);
                add_edge (1,5,INF,-3);
                add_edge (1,6,INF,-2);
                add_edge (1,7,INF,-1);
                add_edge (1,8,INF,-2);
                add_edge (1,9,INF,-1);
    
                add_edge (2,4,INF,-2);
                add_edge (2,5,INF,-1);
                add_edge (2,6,INF,-3);
                add_edge (2,7,INF,-2);
                add_edge (2,8,INF,-1);
                add_edge (2,9,INF,-3);
    
                add_edge (3,4,INF,-1);
                add_edge (3,5,INF,-2);
                add_edge (3,6,INF,-1);
                add_edge (3,7,INF,-3);
                add_edge (3,8,INF,-3);
                add_edge (3,9,INF,-2);
    
                add_edge (4,10,v[0],0);
                add_edge (5,10,v[1],0);
                add_edge (6,10,v[2],0);
                add_edge (7,10,v[3],0);
                add_edge (8,10,v[4],0);
                add_edge (9,10,v[5],0);
                mcmf ();
                printf ("%d
    ",-mincost);
        }    
        return 0;
    }
    

    Problem G

    我们可以发现,我们的最优策略就是在我可以先完成这个任务的时候,那么我们先完成这个任务但是不提交,我们可以在对方完成的前一秒提交好贱啊,这样就浪费了对面的最多时间,然后这个时候我们却在做其他题目,这是最贪心的做法了,然后写一个dp就可以了。

    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<map>
    #include<iostream>
    #include<cstring>
    #include<cmath>
    using namespace std;
    #define rep(i,f_start,f_end) for (int i=f_start;i<=f_end;++i)
    #define per(i,n,a) for (int i=n;i>=a;i--)
    #define MT(x,i) memset(x,i,sizeof(x) )
    #define rev(i,start,end) for (int i=start;i<end;i++)
    #define inf 0x3f3f3f3f
    #define mp(x,y) make_pair(x,y)
    #define lowbit(x) (x&-x)
    #define MOD 1000000007
    #define exp 1e-8
    #define N 1000005 
    #define fi first 
    #define se second
    #define pb push_back
    typedef long long ll;
    const ll INF=1e18+7;;
    typedef vector <int> VI;
    typedef pair<int ,int> PII;
    typedef pair<int ,PII> PIII;
    ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
    ll lcm(ll a,ll b){return a/gcd(a,b)*b;};
    void check_max (int &a,int b) { a=max (a,b);}
    void check_min (int &a,int b) { a=min (a,b);}
    const int maxn=2e3+1;
    int t;
    vector <vector <ll>> dp (maxn,vector <ll> (maxn,0));
    ll a[maxn],b[maxn];
    
    int main () {
        scanf ("%d",&t);
        while (t--) {
            int n;
            scanf ("%d",&n);
            rep (i,1,n) scanf ("%lld",&a[i]);
            rep (i,1,n) {
                scanf ("%lld",&b[i]);
                b[i]+=b[i-1];
            }
            dp.assign (n+1,vector <ll> (n+1,INF));;
            dp[0][0]=0;
            rep (i,1,n) {
                rep (j,0,i) {
                    if (dp[i-1][j-1]+a[i]>b[i]||j==0) dp[i][j]=dp[i-1][j];
                    else dp[i][j]=min (dp[i-1][j],dp[i-1][j-1]+a[i]);
                }
            } 
            per (i,n,1) if (dp[n][i]!=INF) {
                printf ("%d
    ",i);
                break;
            }
        }
        
        return 0;
    }
    
  • 相关阅读:
    ASP.NET MVC案例——————拦截器
    Windows Azure Virtual Network (10) 使用Azure Access Control List(ACL)设置客户端访问权限
    Windows Azure Storage (20) 使用Azure File实现共享文件夹
    Windows Azure HandBook (5) Azure混合云解决方案
    Windows Azure Service Bus (6) 中继(Relay On) 使用VS2013开发Service Bus Relay On
    Azure PowerShell (9) 使用PowerShell导出订阅下所有的Azure VM的Public IP和Private IP
    Windows Azure Service Bus (5) 主题(Topic) 使用VS2013开发Service Bus Topic
    Azure China (9) 在Azure China配置CDN服务
    Windows Azure Storage (19) 再谈Azure Block Blob和Page Blob
    Windows Azure HandBook (4) 分析Windows Azure如何处理Session
  • 原文地址:https://www.cnblogs.com/hhlya/p/13756544.html
Copyright © 2011-2022 走看看