zoukankan      html  css  js  c++  java
  • 2019 CCPC-Wannafly Winter Camp Div2 Day1

    补题进度 7/11

    J 夺宝奇兵

    范围较小,直接枚举靠多少票赢即可,不够的票从小到大买

    #include<bits/stdc++.h>
    #define ll long long
    const int maxn = 1005;
    using namespace std;
    struct node
    {
        ll id,val;
        int pos;
    }p[maxn],P[maxn];
    bool vis[maxn];
    bool cmp(node u,node v)
    {
        return u.val<v.val;
    }
    bool cmp2(node u,node v)
    {
        if(u.id==v.id) return u.val>v.val;
        return u.id<v.id;
    }
    int main()
    {
        int n,m;
        cin>>n>>m;
        for(int i=1; i<=m; i++)
        {
            cin>>p[i].val>>p[i].id;
            p[i].pos=i;
            P[i]=p[i];
        }
        ll ans=1e18;
        sort(P+1,P+1+m,cmp);
        sort(p+1,p+1+m,cmp2);
        for(int i=1; i<=m; i++)
        {
            memset(vis,0,sizeof(vis));
            int have=0;//当前有的票
            int need=i;//赢需要多少票
            int x=0;
            ll val=0;
            for(int j=1; j<=m; j++)
            {
                if(p[j].id!=p[j-1].id) x=1;
                else x++;
                if(x>need) //别人票数大于你赢时需要的票数
                {
                    have++;
                    val+=p[j].val;
                    vis[p[j].pos]=1;
                }
            }
            if(have<=need) 
            {
                for(int j=1; j<=m; j++)
                {
                    if(!vis[P[j].pos])
                    {
                        vis[P[j].pos]=1;
                        have++;
                        val+=P[j].val;
                        if(have>need) break;
                    }
                }
            }
            if(have>need)
            ans=min(ans,val);
           // cout<<i<<" "<<ans<<endl;
        }
        cout<<ans<<endl;
    }
    View Code

    F 爬爬爬山

    我们很容易知道,当其他山大于第一座山+体力值时,此个山是到达不到的。所以我们在遇到这种情况的时候,我们直接把需要把减掉的花费建到边权就ok了,然后跑dij

    #include<bits/stdc++.h>
    #define FIN freopen("input.txt","r",stdin)
    #define ll long long
    #define mod 998244353
    const int maxn = 100005;
    using namespace std;
    int h[maxn],Next[maxn*20],head[maxn],To[maxn*20];
    ll len[maxn*20],dis[maxn];
    bool vis[maxn];
    int cnt,n;
    inline void add(int u,int v,ll w)
    {
        Next[++cnt]=head[u];
        head[u]=cnt;
        To[cnt]=v;
        len[cnt]=w;
    }
    void dij()
    {
        for(int i=1;i<=n;i++)
            dis[i]=2e18;
        dis[1]=0;
        priority_queue<pair<ll,int> ,vector<pair<ll,int> > , greater< pair<ll,int> > >q;
        q.push(make_pair(0,1));
        while(!q.empty())
        {
            pair<ll,int> tmp=q.top();
            q.pop();
            int u=tmp.second;
            if(vis[u]) continue;
            vis[u]=1;
            for(int i=head[u];i!=-1;i=Next[i])
            {
                int v=To[i];
                ll d=len[i];
            //    cout<<v<<" "<<len[i]<<endl;
                if(dis[v]>dis[u]+d)
                {
                    dis[v]=dis[u]+d;
                    q.push(make_pair(dis[v],v));
                }
            }
        }
    }
    int main()
    {
       #ifndef ONLINE_JUDGE
        FIN;
       #endif
    
        memset(head,-1,sizeof(head));
        int m;
        ll k;
        cin>>n>>m>>k;
        for(int i=1;i<=n;i++)
        {
            cin>>h[i];
        }
        for(int i=1;i<=m;i++)
        {
            int u,v;
            ll w;
            cin>>u>>v>>w;
                add(u,v,w+max(0LL,(h[v]-h[1]-k))*max(0LL,(h[v]-h[1]-k)));
                add(v,u,w+max(0LL,(h[u]-h[1]-k))*max(0LL,(h[u]-h[1]-k)));
        }
        dij();
        cout<<dis[n]<<endl;
    }
    View Code

    B 吃豆豆

    数据是10*10的二维矩阵,数据特别小,我们直接对于每秒直接算暴力算此秒的值就好了

    #include<bits/stdc++.h>
    #define FIN freopen("input.txt","r",stdin)
    #define ll long long
    #define mod 998244353
    const int maxn = 100005;
    using namespace std;
    ll dp[11][11][20000];
    int dir[5][2]={1,0,-1,0,0,-1,0,1,0,0};
    bool vis[11][11][20000];
    int T[11][11];
    int main()
    {
       #ifndef ONLINE_JUDGE
        FIN;
       #endif
       int n,m,c;
       cin>>n>>m>>c;
       for(int i=1;i<=n;i++)
           for(int j=1;j<=m;j++)
               cin>>T[i][j];
       int xs,ys,xt,yt;
       cin>>xs>>ys>>xt>>yt;
       vis[xs][ys][0]=1;
      for(int k=1;;k++)
      {
           for(int i=1;i<=n;i++)
               for(int j=1;j<=m;j++)
               {
                   if(!vis[i][j][k-1]) continue;
                for(int p=0;p<5;p++)
                {
                    int x=i+dir[p][0];
                    int y=j+dir[p][1];
                    if(x<1||x>n||y<1||y>m) continue;
                    vis[x][y][k]=1;
                    if(k%T[x][y]==0)
                        dp[x][y][k]=max(dp[x][y][k],dp[i][j][k-1]+1);
                    else dp[x][y][k]=max(dp[x][y][k],dp[i][j][k-1]);
                    if(x==xt&&y==yt&&dp[x][y][k]>=c)
                    {
                        cout<<k<<endl;
                        return 0;
                    }
                }
               }
      }
    }
    View Code

    C 拆拆拆数

    直接拆成两个数(待证)

    #include<bits/stdc++.h>
    #define FIN freopen("input.txt","r",stdin)
    #define ll long long
    #define mod 998244353
    const int maxn = 3000005;
    using namespace std;
    ll prime[1005];
    bool isprime[1005];
    int main()
    {
       #ifdef ONLINE_JUDGE
       #else 
        FIN;
       #endif
    
        int n,cnt=0;
        cin>>n;
        for(int i=2;i<=1000;i++)
        {
             if(isprime[i]==0)
             {
                 prime[++cnt]=i;
                 for(int j=1;j*i<=1000;j++)
                 {
                     isprime[i*j]=1;
                 }
             }
        }
        while(n--)
         {
             ll a,b;
             cin>>a>>b;
             if(__gcd(a,b)==1)
                 cout<<1<<"
    "<<a<<" "<<b<<"
    ";
             else 
             {
                for(int i=1;i<=cnt;i++)
                {
                    if(__gcd(a-prime[i],prime[i])==1&&(__gcd(prime[i],b-prime[i])==1))
                    {
                        cout<<2<<"
    ";
                        cout<<a-prime[i]<<" "<<prime[i]<<"
    ";
                        cout<<prime[i]<<" "<<b-prime[i]<<"
    ";
                        break;
                    }
                }
             }
         }
    }
    View Code

    I 起起落落

    题目是求 p[2k1]>p[2k+1]>p[2k]​的子序列有多少个。 我们定义dp[i] 表示前i个有多少个满足要求的子序列。

    思路:dp[i]的值 可以由dp[1~i-2]得到 我们定义k代表可以使用的中间点

    当a[1~i-2]>a[i]时我们可以直接算贡献 为(dp[]+1)*k  当a[2~i-2]<a[i]时我们都能讲此点作为中间点 k++;

    #include<bits/stdc++.h>
    #define FIN freopen("input.txt","r",stdin)
    #define ll long long
    #define mod 1000000007
    const int maxn = 2000+5;
    using namespace std;
    ll dp[maxn];
    int a[maxn];
    int main()
    {
       #ifndef ONLINE_JUDGE
        FIN;
       #endif
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        int ans=0;
        for(int i=3;i<=n;i++)  //枚举右端点
        {
            int k=a[i]>a[i-1];
            for(int j=i-2;j>=1;j--)
            {
                if(a[j]>a[i])
                    dp[i]=(dp[i]+(dp[j]+1)*k)%mod;
                else if(a[j]<a[i])
                    k++;
            }
    
            ans=(ans+dp[i])%mod;
        }
       cout<<ans<<endl;
    }
    View Code

    A 机器人

    分类讨论即可 我们会发现我们最多传送两次即可走到所有点

    最后可以分为两类:1.都在a区 答案直接为s点到最左点的特殊点和s到最右的特殊点的两倍

                                     2.b区有 答案为1类答案再加上 2*k

    要注意的是 a区 起点可作为转向点

    详细可以参考如下博客:https://blog.csdn.net/CaprYang/article/details/86655459

    代码同上~

    E 流流流动

    树形dp 按题意写即可~

    #include<bits/stdc++.h>
    #define FIN freopen("input.txt","r",stdin)
    #define ll long long
    #define mod 1000000007
    const int maxn = 300+5;
    using namespace std;
    int head[maxn],To[maxn*20],Next[maxn*20];
    int f[maxn],d[maxn],dp[maxn][2],cnt;
    bool vis[maxn];
    inline void add(int u,int v)
    {
        Next[++cnt]=head[u];
        head[u]=cnt;
        To[cnt]=v;
    }
    
    void dfs(int u,int fa)
    {
        vis[u]=1;
        dp[u][0]=0;
        dp[u][1]=f[u];
        for(int i=head[u];i!=-1;i=Next[i])
        {
            int v=To[i];
            if(v==fa) continue;
            dfs(v,u);
            dp[u][0]+=max(dp[v][1],dp[v][0]);
            dp[u][1]+=max(dp[v][0],dp[v][1]-d[min(u,v)]);
        }
    }
    
    int main()
    {
     #ifndef ONLINE_JUDGE
        FIN;
       #endif
    
        memset(head,-1,sizeof(head));
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)
            cin>>f[i];
        for(int i=1;i<=n;i++)
            cin>>d[i];
        
        for(int i=2;i<=n;i++)
        {
            if(i&1) {
                add(i,3*i+1);add(3*i+1,i);
            }
            else {
                add(i,i/2);add(i/2,i);
            }
        }
        int ans=0;
        for(int i=1;i<=n;i++)
        {
            if(!vis[i])
            {
                dfs(i,0);
                ans+=max(dp[i][0],dp[i][1]);
            }
        }
        cout<<ans<<"
    ";
    }
    View Code

    K 星球大战

    unsolved

    H 我爱割葱

    unsolved

    代更

  • 相关阅读:
    移动设备(手机)的唯一ID有哪些
    公司跟你聊企业文化了吗
    C#并行编程-线程同步原语
    C#并行编程-并发集合
    C#并行编程-Task
    C#并行编程-Parallel
    C#并行编程-相关概念
    C#学习系列-this的使用
    C#学习系列-out与ref的区别
    C#学习系列-抽象方法与虚拟方法的区别
  • 原文地址:https://www.cnblogs.com/MengX/p/10326116.html
Copyright © 2011-2022 走看看