uoj #110. 【APIO2015】Bali Sculptures

#110. 【APIO2015】Bali Sculptures

印尼巴厘島的公路上有許多的雕塑,咱們來關注它的一條主幹道。ios

在這條主幹道上一共有 NN 座雕塑,爲方便起見,咱們把這些雕塑從 11 到 NN 連續地進行標號,其中第 ii 座雕塑的年齡是 YiYi 年。爲了使這條路的環境更加優美,政府想把這些雕塑分紅若干組,並經過在組與組之間種上一些樹,來吸引更多的遊客來巴厘島。ide

下面是將雕塑分組的規則:atom

  • 這些雕塑必須被分爲剛好 XX 組,其中 AXBA≤X≤B,每組必須含有至少一個雕塑,每一個雕塑也必須屬於且只屬於一個組。同一組中的全部雕塑必須位於這條路的連續一段上。
  • 當雕塑被分好組後,對於每一個組,咱們首先計算出該組全部雕塑的年齡和。
  • 計算全部年齡和按位取或的結果。咱們這個值把稱爲這一分組的最終優美度。

請問政府能獲得的最小的最終優美度是多少?spa

備註:將兩個非負數 PP 和 QQ 按位取或是這樣進行計算的:code

  • 首先把 PP 和 QQ 轉換成二進制。
  • 設 nPnP 是 PP 的二進制位數,nQnQ 是 QQ 的二進制位數,MM 爲 nPnP 和 nQnQ 中的最大值。PP 的二進制表示爲 pM1pM2p1p0pM−1pM−2…p1p0,QQ 的二進制表示爲 qM1qM2q1q0qM−1qM−2…q1q0,其中 pipi 和 qiqi 分別是 PP 和 QQ 二進制表示下的第 ii 位,第 M1M−1 位是數的最高位,第 00 位是數的最低位。
  • PP 與 QQ 按位取或後的結果是: (pM1ORqM1)(pM2ORqM2)(p1ORq1)(p0ORq0)(pM−1ORqM−1)(pM−2ORqM−2)…(p1ORq1)(p0ORq0)。其中:
    • 0OR0=00OR0=0
    • 0OR1=10OR1=1
    • 1OR0=11OR0=1
    • 1OR1=11OR1=1

輸入格式

輸入的第一行包含三個用空格分開的整數 N,A,BN,A,B。orm

第二行包含 NN 個用空格分開的整數 Y1,Y2,,YNY1,Y2,…,YN。xml

輸出格式

輸出一行一個數,表示最小的最終優美度。blog

樣例一

input

6 1 3
8 1 2 1 5 4

output

11

explanation

將這些雕塑分爲 22 組,(8,1,2)(8,1,2) 和 (1,5,4)(1,5,4),它們的和是 (11)(11) 和 (10)(10),最終優美度是 (11OR10)=11(11OR10)=11。(不難驗證,這也是最終優美度的最小值。)ci

子任務

  • 子任務 1 (9 分)
    • 1N201≤N≤20
    • 1ABN1≤A≤B≤N
    • 0Yi10000000000≤Yi≤1000000000
  • 子任務 2 (16 分)
    • 1N501≤N≤50
    • 1ABmin{20,N}1≤A≤B≤min{20,N}
    • 0Yi100≤Yi≤10
  • 子任務 3 (21 分)
    • 1N1001≤N≤100
    • A=1A=1
    • 1BN1≤B≤N
    • 0Yi200≤Yi≤20
  • 子任務 4 (25 分)
    • 1N1001≤N≤100
    • 1ABN1≤A≤B≤N
    • 0Yi10000000000≤Yi≤1000000000
  • 子任務 5 (29 分)
    • 1N20001≤N≤2000
    • A=1A=1
    • 1BN1≤B≤N
    • 0Yi10000000000≤Yi≤1000000000

時間限制1s1sinput

空間限制64MB

 

 

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 110
using namespace std;
int n,A,B,w[maxn],cnt;
long long b[maxn],ans=1000000000000000LL;
long long check(int sta){
    long long res=0;
    cnt=1;
    b[1]=0;
    for(int i=1;i<n;i++){
        b[cnt]+=w[i];
        if(sta&(1<<(i-1))){
            res|=b[cnt];
            cnt++;
            b[cnt]=0;
        }
        if(cnt>B)return -1;
    }
    if(cnt<A)return -1;
    b[cnt]+=w[n];
    res|=b[cnt];
    return res;
}
int main(){
    scanf("%d%d%d",&n,&A,&B);
    for(int i=1;i<=n;i++)scanf("%d",&w[i]);
    for(int i=0;i<(1<<(n-1));i++){
        long long now=check(i);
        if(now!=-1)
            ans=min(ans,now);
    }
    cout<<ans<<endl;
}
9分 暴力
#include<iostream>
#include<cstdio>
#include<cstring>
#define INF 0x3f3f3f3f
#define maxn 2010
using namespace std;
int f[105][105],g[maxn],n,A,B;
long long a[maxn],sum[maxn],ans;
void solve1(){
    for(int pos=45;pos>=0;pos--){
        memset(f,1,sizeof(f));
        f[0][0]=0;
        for(int i=1;i<=n;i++)
        for(int j=1;j<=B;j++)
        for(int k=0;k<i;k++)
            if(f[k][j-1]==0 && (((sum[i]-sum[k])>>pos)&1)==0 && (((sum[i]-sum[k])|ans)>>pos)==(ans>>pos)){
                f[i][j]=0;
                break;
            }
        bool flag=0;
        for(int i=A;i<=B;i++)
            if(f[n][i]==0){flag=1;break;}
        if(!flag)ans|=1LL<<pos;
    }
    cout<<ans<<endl;
}
void solve2(){
    for(int pos=51;pos>=0;pos--){
        for(int i=1;i<=n;i++)g[i]=INF;
        g[0]=0;
        for(int i=1;i<=n;i++)
            for(int j=0;j<i;j++){
                if((((sum[i]-sum[j])>>pos)&1))continue;
                if((((sum[i]-sum[j])|ans)>>pos)==(ans>>pos))
                    g[i]=min(g[i],g[j]+1);
            }
        if(g[n]>B)ans|=1LL<<pos;
    }
    cout<<ans<<endl;
}
int main(){
    scanf("%d%d%d",&n,&A,&B);
    for(int i=1;i<=n;i++){
        cin>>a[i];
        sum[i]=sum[i-1]+a[i];
    }
    if(A==1)solve2();
    else solve1();
    return 0;
}
100分 動態規劃
相關文章
相關標籤/搜索