zoukankan      html  css  js  c++  java
  • Codeforces Round #322 (Div. 2) E F

    E. Kojiro and Furrari
    题意说的是 在一条直线上 有n个加油站, 每加一单位体积的汽油 可以走1km 然后每个加油站只有一种类型的汽油,汽油的种类有3种 求从起点出发到达终点要求使用最少的 1 号汽油的前提下使用最少的二号汽油,
    我们可以这样考虑
    当前在第i个加油站的时候         i个加油站 有3种情况
    第一种 他是只有 1 号汽油 那么他必须携带 尽量少的 1号汽油到达离他最近的2号汽油点或者3号汽油点 更新这个点到达终点的代价 取最小值,因为他必须通过那个点到达其他点
    第二种 他只有 2 号汽油, 那么他必须携带 尽量多的 2号汽油到达能达到的最远的1号汽油点,这样可以更少使用1号汽油,或者 带尽量少的汽油到达离他最近的3号汽油的点,或者最近的2号汽油的点
    第三种 如果他是3号汽油 那么他必须携带尽量少的3号汽油到达离他最近的点,或者带尽量多的3号汽油到达离他能达到的最远的1 、2号汽油点
    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <string.h>
    #include <vector>
    using namespace std;
    typedef long long LL;
    const int maxn=200005;
    const int INF=2147483647;
    struct point{
      int x,t;
      point(int cx=0, int ct=0){
         x=cx; t=ct;
      }
      bool operator <(const point &rhs)const{
         return x<rhs.x;
      }
    }P[maxn];
    int D[4][maxn],num[4];
    int dp[maxn][3];
    int e,s,n,m;
    int bitlook1(int x,int *C, int n)
    {
         int L=0,R=n-1,ans=-1;
         while(L<=R)
            {
                 int mid=(L+R)>>1;
                 int id=C[mid];
                 if( P[id].x>=x  ){
                    ans=mid;
                    R=mid-1;
                 }else{
                    L=mid+1;
                 }
            }
            return ans;
    }
    void cmp(int &A, int &B,int &V, int C, int D, int DV)
    {
          if(A>=C){
             if(A==C){
                if(B<D) return ;
                if(B>D){
                    B=D;
                    V=DV;
                }else{
                   V=min(V,DV);
                }
             }
             else {
                A=C; B=D;
                V=DV;
             }
          }
    }
    void solve1(int id)
    {
         int loc=P[id].x;
         int d1=bitlook1(loc+1,D[1],num[1]);
         int d2=bitlook1(loc+1,D[2],num[2]);
         int d3=bitlook1(loc+1,D[3],num[3]);
         if(d3!=-1)d3=D[3][d3];
         if(d2!=-1)d2=D[2][d2];
         if(d1!=-1)d1=D[1][d1];
         if( d3!=-1 && P[d3].x <= loc+s )
         {
              int cp1 = dp[d3][1]+P[d3].x-loc;
              int cp2 = dp[d3][2];
              cmp(dp[id][1],dp[id][2],dp[id][0],cp1,cp2,P[d3].x-loc);
         }
         if(d2!=-1 && P[d2].x<=loc+s)
         {
              int cp1 = dp[d2][1]+P[d2].x-loc;
              int cp2 = dp[d2][2];
              cmp(dp[id][1],dp[id][2],dp[id][0],cp1,cp2,P[d2].x-loc);
         }
        if( d1!=-1 && P[d1].x<=loc+s)
         {
             int cp1 = dp[d1][1]+P[d1].x-loc;
             int cp2 = dp[d1][2];
              cmp(dp[id][1],dp[id][2],dp[id][0],cp1,cp2,P[d1].x-loc);
         }
    }
    int bitlook2(int x,int *C, int n)
    {
         int L=0,R=n-1,ans=-1;
         while(L<=R)
            {
                 int mid=(L+R)>>1;
                 int id=C[mid];
                 if( P[id].x<=x  ){
                    ans=mid;
                    L=mid+1;
                 }else{
                    R=mid-1;
                 }
            }
            return ans;
    }
    void solve2(int id)
    {
         int loc=P[id].x;
         int d1=bitlook2(loc+s,D[1],num[1]);
         int d2=bitlook1(loc+1,D[2],num[2]);
         int d3=bitlook1(loc+1,D[3],num[3]);
         if(d3!=-1)d3=D[3][d3];
         if(d2!=-1)d2=D[2][d2];
         if(d1!=-1)d1=D[1][d1];
         if( d3!=-1 && P[d3].x <= loc+s )
         {
              int cp1 = dp[d3][1];
              int cp2 = dp[d3][2]+P[d3].x-loc;
              cmp(dp[id][1],dp[id][2],dp[id][0],cp1,cp2,P[d3].x-loc);
         }
         if(d2!=-1 && P[d2].x<=loc+s)
         {
              int cp1 = dp[d2][1];
              int cp2 = dp[d2][2]+P[d2].x-loc;
              cmp(dp[id][1],dp[id][2],dp[id][0],cp1,cp2,P[d3].x-loc);
         }
    
        if( d1!=-1&&P[d1].x>loc)
         {
             int cp0=s;
             int lit = s-(P[d1].x-loc);
             int cp1 = dp[d1][1]-min(lit,dp[d1][0]);
             int cp2 = dp[d1][2]+cp0;
              cmp(dp[id][1],dp[id][2],dp[id][0],cp1,cp2,cp0);
         }
    }
    void solve3(int id)
    {
         int loc=P[id].x;
         int d1=bitlook2(loc+s,D[1],num[1]);
         int d2=bitlook2(loc+s,D[2],num[2]);
         int d3=bitlook1(loc+1,D[3],num[3]);
          if(d3!=-1)d3=D[3][d3];
         if(d2!=-1)d2=D[2][d2];
         if(d1!=-1)d1=D[1][d1];
    
         if( d3!=-1 && P[d3].x<=loc+s )
         {
             cmp(dp[id][1],dp[id][2],dp[id][0],dp[d3][1],dp[d3][2],0);
         }
         if(d2!=-1&&P[d2].x>loc)
         {
             int lit = s-(P[d2].x-loc);
             int cp1 = dp[d2][1];
             int cp2 = dp[d2][2]-min(dp[d2][0],lit);
             cmp(dp[id][1],dp[id][2],dp[id][0],cp1,cp2,0);
         }
         if(d1!=-1&&P[d1].x>loc)
         {
             int lit = s-(P[d1].x-loc);
             int cp1 = dp[d1][1]-min(dp[d1][0],lit);
             int cp2 = dp[d1][2];
             cmp(dp[id][1],dp[id][2],dp[id][0],cp1,cp2,0);
         }
    }
    void solve4(int loc, int &S1,int &S2)
    {
         int k;
         int d1=bitlook2(loc+s,D[1],num[1]);
         int d2=bitlook2(loc+s,D[2],num[2]);
         int d3=bitlook1(loc+1,D[3],num[3]);
         if(d3!=-1)d3=D[3][d3];
         if(d2!=-1)d2=D[2][d2];
         if(d1!=-1)d1=D[1][d1];
         if( d3!=-1 && P[d3].x<=loc+s &&dp[d3][1]!=INF)
         {
             cmp(S1,S2,k,dp[d3][1],dp[d3][2],0);
         }
         if(d2!=-1&&P[d2].x>loc&&dp[d2][1]!=INF)
         {
             int lit = s-(P[d2].x-loc);
             int cp1 = dp[d2][1];
             int cp2 = dp[d2][2]-min(dp[d2][0],lit);
             cmp(S1,S2,k,cp1,cp2,0);
         }
         if(d1!=-1&&P[d1].x>loc&&dp[d1][1]!=INF)
         {
             int lit = s-(P[d1].x-loc);
             int cp1 = dp[d1][1]-min(dp[d1][0],lit);
             int cp2 = dp[d1][2];
             cmp(S1,S2,k,cp1,cp2,0);
         }
    }
    int main()
    {
        while(scanf("%d%d%d%d",&e,&s,&n,&m)==4)
            {
                 num[0]=num[1]=num[2]=num[3]=0;
                  int k=0;
                 for(int i=0; i<n; i++) {
                        scanf("%d%d",&P[k].t,&P[k].x);
                    if(P[k].x<e)k++;
                }
                n=k;
                 sort(P,P+n);
                 if(P[n-1].x!=e)
                 {
                     P[n]=point(e,3);
                     n++;
                 }
                 for(int i=0; i<n; i++)
                    if(P[i].t==1) D[ 1 ][num[1]++ ] =i;
                    else if(P[i].t==2) D[2][ num[2] ++ ]=i;
                    else D[3][ num[3]++ ]=i;
                dp[n-1][0]=dp[n-1][1]=dp[n-1][2]=0;
                for(int i=n-2; i>=0;i--)dp[i][0]=dp[i][1]=dp[i][2]=INF;
    
                for(int i=n-2; i>=0; i--)
                    {
                           if(P[i].t==1)solve1(i);
                           else if(P[i].t==2)solve2(i);
                           else solve3(i);
                           if(dp[i][1]==INF)break;
                    }
                for(int i=0;i<m; i++)
                {
                     int S1=INF,S2=INF;
                     int loc;
                     scanf("%d",&loc);
                     solve4(loc,S1,S2);
                     if(S1==INF){
                         printf("-1 -1
    ");
                     }else{
                         printf("%d %d
    ",S1,S2);
                     }
                }
            }
        return 0;
    }
    /*
    386 20 1 1
    2 369
    351
    
    */
    View Code

    F. Zublicanes and Mumocrates 树形dp

    题意给了一棵树 要求使得这棵树所有的节点分为两个阵营,其中叶子节点要均分,求最少的两个阵营相邻, 也就是求 最少的边使得 这些边两头阵营不同 

    dp[cur][i][j] 表示当cur为i阵营的时候 有j个和i同阵营的方案

    dp[cur][i][j+k] = min{dp[to][i^1][j=(叶子个数-d)]+dp[cur][i][k]+1,dp[to][i][j]+dp[cur][i][k]}

    cnt为叶子节点的个数 最后答案是 min{ dp[root][0][cnt/2] ,dp[root][1][cnt/2]}

    #include <algorithm>
    #include <string.h>
    #include <cstdio>
    #include <iostream>
    using namespace std;
    const int maxn=5005;
    int H[maxn],to[maxn*2],nx[maxn*2],numofE;
    void add(int u, int v)
    {
         numofE++;
         to[numofE]=v;
         nx[numofE]=H[u];
         H[u]=numofE;
    }
    int dp[maxn][2][maxn];
    int dp2[2][maxn],sz[maxn];
    int d[maxn];
    void dfs(int cur ,int per)
    {
          if(d[cur]==1){
             sz[cur]=1;
             dp[cur][0][1]=dp[cur][1][1]=0;
             return ;
          }
          dp[cur][0][0]=dp[cur][1][0]=0;
          for(int i=H[cur]; i ; i=nx[i])
            {
                  int tto = to[i];
                  if(tto==per)continue;
                   dfs(tto,cur);
                 for(int i=0; i<=sz[cur]; i++)
                     for(int u=0; u<2; u++)
                      {
                          if( dp[cur][u][i] == -1 ) continue;
    
                          for(int j=0; j<=sz[tto]; j++)
                          for(int v=0; v<2; v++)
                            {
                                if(dp[tto][v][j]==-1)continue;
                                if(u==v)
                                {
                                    if(dp2[u][i+j]==-1)
                                    {
                                         int k=dp[cur][u][i]+dp[tto][v][j];
                                        dp2[u][i+j] = k;
    
                                    }else {
                                          int k=min(dp[cur][u][i]+dp[tto][v][j],dp2[u][i+j]);
                                        dp2[u][i+j]=k;
    
                                    }
                                }else
                                {
                                    int nu=sz[tto];
                                    if(dp2[u][i+nu-j]==-1)
                                       {
                                           int k=dp[cur][u][i]+dp[tto][v][j]+1;
                                           dp2[u][i+nu-j]=k;
                                       }
                                    else
                                        {
                                        int k=min(dp[cur][u][i]+dp[tto][v][j]+1,dp2[u][i+nu-j]);
                                        dp2[u][i+nu-j]=k;
    
                                        }
                                }
                            }
                      }
                 sz[cur]+=sz[tto];
                 for(int i=0; i<=sz[cur]; i++)
                    for(int j=0; j<2; j++)
                    {
                          dp[cur][j][i]=dp2[j][i];
                          dp2[j][i]=-1;
                    }
            }
    }
    int main()
    {
        int n;
        while(scanf("%d",&n)==1)
            {
                 memset(d,0,sizeof(d));
                 memset(dp,-1,sizeof(dp));
                 memset(sz,0,sizeof(sz));
                 memset(dp2,-1,sizeof(dp2));
                 memset(H,0,sizeof(H));
                 numofE=0;
                for(int i=1; i<n; i++)
                    {
                        int a,b;
                        scanf("%d%d",&a,&b);
                        add(a,b);
                        add(b,a);
                        d[a]++;d[b]++;
                    }
                if(n==2){
                    printf("%d
    ",1); continue;
                }
                int root;
                int cnt=0;
                for(int i=1; i<=n; i++){
                    if(d[i]==1)cnt++;
                    else root=i;
                }
                dfs(root,-1);
                printf("%d
    ",min(dp[root][0][cnt/2],dp[root][1][cnt/2]));
            }
        return 0;
    }
    /*
    6
    1 2
    2 5
    2 3
    3 4
    3 6
    */
    View Code
  • 相关阅读:
    JDK代理(必须代理类要实现一个接口)
    Spring整合jdbc
    Python 之正则匹配
    Spark ML 之 LR逻辑回归实现排序
    Spark 之 读取配置连接Mysql和上传到HDFS
    Spark ML 之 推荐算法项目(上)
    Spark ML 之 推荐算法项目(下)
    Spark ML 之 ALS内存溢出的解决办法
    Spark ML 之 基于协同过滤的召回算法
    Spark ML 特征处理类之 VectorAssembler 向量装配转换器/VectorIndexer
  • 原文地址:https://www.cnblogs.com/Opaser/p/4845287.html
Copyright © 2011-2022 走看看