zoukankan      html  css  js  c++  java
  • 刷题总结——道路覆盖(ssoj)

    题目:

    题目描述

    Tar 把一段凹凸不平的路分成了高度不同的 N 段(每一段相同高度),并用 H[i] 表示第 i 段高度。现在 Tar 一共有 n 种泥土可用,它们都能覆盖给定的连续的 k 个部分。
    对于第 i 种泥土,它的价格为 C[i],可以使得区间 [i,min(n,i+k-1)] 的路段的高度增加 E[i]。
    Tar 要设定一种泥土使用计划,使得使用若干泥土后,这条路最低的高度尽量高,并且这个计划必须满足以下两点要求:
    (1)每种泥土只能使用一次。
    (2)泥土使用成本必须小于等于 M 。
    请求出这个最低的高度最高是多少。

    输入格式

    第一行为如上文所示的三个正整数:N,M,K。
    接下来 N 行,每行3个如上文所示的正整数 H[i],E[i],C[i]。

    输出格式

    输出有且只有一个数字,为最底部分的高度的最大值。

    样例数据 1

    输入  [复制]

     
    4 20 1 
    1 3 5 
    1 7 3 
    4 6 9 
    3 5 13

    输出

    3

    备注

    【数据范围】
    对于 30% 的数据:N≤20。
    对于 100% 的数据:1≤K≤11;1≤N≤100;0≤M,H[i],E[i],C[i]≤1000000。

    题解:

    引用ssoj官网题解:

    二分+DP
    二分答案ans,问题转化为了判定性问题。判定的方法是:每个位置都能到达高度ans的最小费用cost是否<=M。
    注意到1<=K<=11,也就是说对于第i个路段,能够提高它高度的泥土只有从第i-K个到第i个。于是使用状态压缩动态规划求cost。f[i][j]表示前i个路段通过泥土使用>=高度ans,且第i - k个到第i个的使用情况为二进制数j

    注意位运算打括号!!!!!!!

    注意dp初始化!!!!!


    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<ctime>
    #include<cctype>
    #include<cstring>
    #include<string>
    #include<algorithm>
    using namespace std;
    const int N=105;
    const int inf=1e+9;
    int n,m,k;
    int h[N],e[N],c[N];
    int bit[15];
    int dp[N][5000],g[5000];
    bool jud[N];
    inline int R()
    {
      int f=0;
      char c;
      for(c=getchar();(c<'0'||c>'9');c=getchar());
      for(;c<='9'&&c>='0';c=getchar())
        f=(f<<3)+(f<<1)+c-'0';
      return f;
    }
    inline int find(int x)
    {
      for(int i=k-1;i>=0;i--)
        if(x>=bit[i])  return i;
    }
    inline bool work(int minn)
    {
      memset(dp,-1,sizeof(dp));
      dp[0][0]=0;
      memset(jud,false,sizeof(jud));
      jud[0]=true;
      for(int i=1;i<=n;i++)
      {
        if(!jud[i-1])  
          return false;
        g[0]=0;
        int maxx=(i<k?bit[i]:bit[k]);
        for(int j=0;j<maxx;j++)
        {
          int temp;
          if(j==0)  g[j]=0;
          else
          {  
            temp=find(j);
            g[j]=g[j-bit[temp]]+e[i-temp];
          }
          if(g[j]+h[i]<minn)  continue; 
          if(dp[i-1][j>>1]==-1&&dp[i-1][(j>>1)+bit[k-1]]==-1)  continue;
          if(dp[i-1][j>>1]==-1)  
            temp=dp[i-1][(j>>1)+bit[k-1]];
          else
          {  
            if(dp[i-1][(j>>1)+bit[k-1]]==-1)
              temp=dp[i-1][j>>1];
            else
              temp=min(dp[i-1][j>>1],dp[i-1][(j>>1)+bit[k-1]]);  
          }
          dp[i][j]=temp+(j&1)*c[i];
          if(dp[i][j]>m)  dp[i][j]=-1;
          else jud[i]=true;
        }
      }
      return jud[n];
    }
    int main()
    {
     // freopen("a.in","r",stdin);
      n=R(),m=R(),k=R();
      for(int i=1;i<=n;i++)
        h[i]=R(),e[i]=R(),c[i]=R();
      bit[0]=1;
      for(int i=1;i<=k;i++)
        bit[i]=bit[i-1]*2;
      int left=inf,right;
      for(int i=1;i<=n;i++)
        left=min(left,h[i]);
      right=h[1]+e[1];
      for(int i=1;i<=n;i++)
      {
        int temp=h[i];
        for(int j=i;j>=i-k+1&&j>=1;j--)
          temp+=e[j];
        right=max(temp,right);
      }
      int ans=left;
      while(left<=right)
      {
        int mid=(left+right)/2;
        if(work(mid))  ans=mid,left=mid+1;
        else  right=mid-1;
      }
      cout<<ans<<endl;
      return 0;
    }
  • 相关阅读:
    pandas去重方法
    原生表单组件
    html表单
    html表格基本标签
    文档和网站架构
    文本格式
    【Leetcode链表】奇偶链表(328)
    【Leetcode链表】移除链表元素(203)
    【Leetcode链表】旋转链表(61)
    【Leetcode链表】反转链表 II(92)
  • 原文地址:https://www.cnblogs.com/AseanA/p/7257158.html
Copyright © 2011-2022 走看看