Codeforces Round #171 (Div. 2)

acm_cxlove發表於2013-03-15

轉載請註明出處,謝謝http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove


A:模擬,然後判斷

B:列舉起點,然後二分最遠的。或者維護兩個指標

C:預處理出up[i],down[i]
      up[i]表示從i開始,非遞減到最遠的位置
      down[i]表示從i往前,非遞減到最遠的位置
     那麼對於某個區間[l,r]只要up[i]<down[i],說明中間還有段區間,否則為YES

D:狀態壓縮DP。
      對於某一個狀態,最高位上的1,說明當前需要用低位相加湊出來。
      所有低位上為1表示當前已經有這個數,否則沒有
      遞迴,記憶化DP,路徑上所有狀態包含1個數的最大值便是解,找到最優解就行了
int n;
int a[23];
int dp[1<<23];
int s[1<<23];
int dfs(int state){
    if(dp[state]<inf)
        return dp[state];
    int ans=inf;
    for(int i=n-1;i>=0;i--){
        if(state&(1<<i)){
            int pre=state^(1<<i);
            for(int j=0;j<i;j++)
                for(int k=0;k<i;k++){
                    if(a[j]+a[k]==a[i]){
                        int cur=pre;
                        cut=cur|(1<<j)|(1<<k)|(1<<(i-1));
                        ans=min(ans,max(dfs(cur),s[cur]));
                    }
                }
            break;
        }
    }
    return dp[state]=ans;
}
int main(){
    for(int i=1;i<(1<<23);i++)
        s[i]=s[i>>1]+(i&1);
    cin>>n;
    for(int i=0;i<n;i++)
        cin>>a[i];
    if(n==1){
        cout<<1<<endl;
        return 0;
    }
    mem(dp,0x3f);
    dp[1]=0;
    dp[0]=0;
    dfs(1<<(n-1));
    cout<<(dp[1<<(n-1)]>=inf?-1:dp[1<<(n-1)])<<endl;
    return 0;
}

E:DP,有兩種情況
    某位是1,在高位為+,然後在低位為-
   所以dp[0][i]表示當前位為+,dp[1][i]表示當前位處於第二種情況

顯然的騙訪問,呵呵~~~

相關文章