zoukankan      html  css  js  c++  java
  • 9.25DAY1T2

    2.巴厘岛的雕塑4401

    (sculpture)

    【问题描述】

      印尼巴厘岛的公路上有许多的雕塑,我们来关注它的一条主干道。 
      在这条主干道上一共有N座雕塑,为方便起见,我们把这些从1到N连续地进行标号,其中第i座雕塑的年龄是Yi年。为了使这条路的环境更加优美,政府想把这些雕塑分成若干组,并通过在组与之间种上一些树,来吸引更多的游客来巴厘岛。 
      下面是将雕塑分组的规则: 
      这些雕塑必须被分为恰好X组,其中A≤X≤B,每组必须含有至少一个雕塑,每个雕塑也必须属于且只一组。同一组中的所有雕塑必须 位于这条路的连续一段上。 
      当雕塑被分好组后,对于每个组,我们首先计算出该组所有雕塑的年龄和,然后计算将每组年龄和按位取或(即对上述年龄和按位取或),我们把按位取或后得到的结果称为这一分组的最终优美度(颜值)。 
      请问政府能得到的最小终优美度(颜值)是多少? 
      备注: 
      将两个非负数P和Q按位取或是这样进行计算的: 
      首先把P和Q转换成二进制:设nP是P的二进制位数,nQ是Q的二进制位数,M为nP和nQ中的最大值。P的二进制表示为pM-1,pM-2,…,p1,p0,Q的二进制表示为qM-1,qM-2,…,q1,q0,其中pi和qi分别是P和Q二进制表示下的第i位,第M-1位是数的最高位,第0位是数的最低位。 
      P与Q按位取或后的结果是:(pM-1或qM-1)(pM-2或qM-2)…(p1或q1)(p0或q0)。其中 : 
        0 或 0 = 0 
        0 或 1 = 1 
        1 或 0 = 1 
        1 或 1 = 1

    【输入】

      输入的第一行包含三个用空格分开的整数N,A和B。 
      第二行包含N个用空格分开的整数Y1,Y2,...,YN。

    【输出】

      输出一行一个数,表示最小的最终优美度。

    【输入样例】

    6 1 3 8 1 2 1 5 4

    【输出样例】

    11

    【样例说明】

      将这些雕塑分为2组,(8,1,2)和(1,5,4),它们的和是(11)和(10),最终优美是(11或10)=11。(不难验证,这也是最终优美度的最小值。) 
    【数据规模与约定】
      共有五部分数据(或称5个子任务)。 
      第1部分数据占9分,数据范围满足:1≤N≤20,1≤A≤B≤N,0≤Yi≤1,000,000,000; 
      第2部分数据占16分,数据范围满足:1≤N≤20,1≤A≤B≤min(20,N),0≤Yi≤10; 
      第3部分数据占21分,数据范围满足:1≤N≤100,A=1,1≤B≤min(20,N),0≤Yi≤20; 
      第4部分数据占25分,数据范围满足:1≤N≤100,1≤A≤B≤N,0≤Yi≤1,000,000,000; 
      第5部分数据占29分,数据范围满足:1≤N≤2000,A=1,1≤B≤N,0≤Yi≤1,000,000,000。

    "显然位运算的极值问题都应该从高位向低位考虑。优先让这一位为0,如果行的话这一位就是0,否则就设为1。" 

    设答案为ans,从高位到低位枚举 是否有使ans的这一位为0的方案,注意到每一位是互相独立的。假设枚举到了倒数第x位, 即ans的最高位到倒数第x+1位的最优01分布已确定,现在正在判断第x位是否有可能填0:

    对于每个x,考虑递推法:

    设 布尔数组 f[i][j]表示:将前i个数分j段,能否在 得到的优美度的最高位到倒数第x+1位 都与ans一致的情况下,让倒数第x位为0 因为段与段之间的合并为or运算,所以

    递推方式为:

    若 将前k个数(k<i)分j-1段,得到的优美度本身与ans一致,并且第j段的优美度也与  ans一致,才可以由f[k][j-1]转移到f[i][j] 如何判断以上两个条件:

    1. 得到的优美度的最高位到倒数第k+1位 是否与ans一致:( (S[i]-S[k])>>k | ans ) == ans (ans为0的位,S[i]-S[k]都不为1)

    2. 得到的优美度的倒数第k位能否为0:( (S[i]-S[k]) & 1<<(k-1) ) == 0 对于每个x,若f[n][A~B]有至少一个为1,nas的第k位就可以为0

     复杂度:O( logY * n^3 )

    对于最后一组数据:A==1,B<=n,段数只有上限  我们要想把f数组的第二个维度省掉的话,用f[i]记录将前i个数分段并得到可行解的最小段数,最后判断其是否小于B,即可。 

    复杂度:O( logY * n^2 )

    注意:1写成1LL,开全局ll

    code:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 using namespace std;
     5 typedef long long ll;
     6 long long len=0;
     7 long long s[1000005],f[2005][2005],g[200005]; 
     8 long long n,a,b,ans=0;
     9 void work1(){
    10     for(int x=len;x>=1;x--){
    11         memset(g,0x3f3f3f3f,sizeof g);
    12         g[0]=0;
    13         for(int i=1;i<=n;i++){
    14             for(int j=0;j<i;j++){
    15                 if(g[j]<b){
    16                     int t=s[i]-s[j];
    17                     if((t>>(ll)x|ans)==ans&&(t&(1ll<<(ll)(x-1)))==0)g[i]=min(g[i],g[j]+1); 
    18                 }
    19             }
    20         }
    21         if(g[n]>b){
    22             ans<<=1;
    23             ans++;
    24         }
    25         else {
    26             ans<<=1;
    27         }
    28     }
    29 }
    30 void work2(){
    31     for(long long x=len;x>=1;x--){
    32         memset(f,0,sizeof f);
    33         f[0][0]=1;
    34         for(long long i=1;i<=n;i++){
    35             for(long long j=1;j<=i;j++){
    36                 for(long long k=0;k<i;k++){
    37                     if(f[k][j-1]){
    38                         long long t=s[i]-s[k];
    39                         if(((t>>(ll)x)|ans)==ans&& (t&(1ll<<x-1ll))==0)f[i][j]=1;
    40                     }
    41                 }
    42             }
    43         }
    44         int i;
    45         for(i=a;i<=b;i++){
    46               if(f[n][i])
    47                   break;
    48         } 
    49         ans<<=1;
    50         if(i>b)ans++;
    51     //    cout<<ans<<endl;
    52     }
    53 }
    54 int main(){
    55     cin>>n>>a>>b;
    56     for(long long i=1;i<=n;i++){
    57         cin>>s[i];
    58         s[i]+=s[i-1];
    59     }
    60     for(int t=s[n];t>0;t>>=1)
    61         len++;
    62     if(a==1)work1();
    63     else work2();
    64     cout<<ans;
    65 }
  • 相关阅读:
    log4net 开启内部调试
    负载均衡的基本算法
    MapReduce算法形式六:只有Map独自作战
    MapReduce算法形式五:TOP—N
    MapReduce算法形式四:mapjoin
    MapReduce算法形式三:cleanup
    MapReduce算法形式二:去重(HashSet)
    MapReduce算法形式二:去重(shuffle)
    MapReduce算法形式一:WordCount
    理解yarn平台,理解万岁,肤浅理解也万岁~
  • 原文地址:https://www.cnblogs.com/saionjisekai/p/9699693.html
Copyright © 2011-2022 走看看