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 }
  • 相关阅读:
    HDU1720 A+B Coming
    HDU1390 ZOJ1383 Binary Numbers
    HDU1390 ZOJ1383 Binary Numbers
    HDU2504 又见GCD
    HDU2504 又见GCD
    HDU1335 POJ1546 UVA389 UVALive5306 ZOJ1334 Basically Speaking
    HDU1335 POJ1546 UVA389 UVALive5306 ZOJ1334 Basically Speaking
    HDU1020 ZOJ2478 Encoding
    HDU1020 ZOJ2478 Encoding
    HDU2097 Sky数
  • 原文地址:https://www.cnblogs.com/saionjisekai/p/9699693.html
Copyright © 2011-2022 走看看