1. 程式人生 > >HOJ 13845 Atomic Computer有向無環圖的動態規劃

HOJ 13845 Atomic Computer有向無環圖的動態規劃

-1 會有 bsp pre 但是 自帶 += 排列組合 開始

考慮任意一個數字,任何一個都會有奇怪的。。性質,就是一個可以保證不重復的方案——直接簡單粗暴的最高位加數字。。於是,如同上面的那個題:+1、-1、0

但是考慮到65536KB的標準內存限制,會得出一個奇怪的性質,那就是。。。這題可以先大表之後對內存做奇怪的優化——前十位開小一點,後十位開大一點。之前計算時間復雜度的時候是1e6*20這種按照全部數組空間掃一發的方式進行計算,但是後面發現,這種方式其實是沒必要,觀察可以發現,實際上這道題不論怎麽做奇怪的計算都是實質上的——也就是窮舉SUM(2^k)。於是。。。。。。全部復雜度大概就被強行限制到了1e6的規模。之後進行任意一種方式查詢即可。。。。查詢復雜度是O(1)

但是最開始的時候踩了個坑——對於數字X應該怎麽做才能夠將他給他多加一位還能夠保證不重復呢?或者說應該把新的數字加到哪裏呢?最開始想到的是末尾,但是看上去末尾不夠好。。。於是考慮往中間加,但是明顯的限制是——排列組合的個數無論如何都不可能、也不能夠,比3^N更多。於是。。。我們可以考慮愉快的吧新的位數加到想象中的二進制串串的最最前面。並且這種做法的直接好處是,可以“制度性的保證不出現重復”。。

這題當時在做的時候打了好長好長的表,試圖進行相關對比。。然而。。。。有向無環圖的動態規劃問題。。。

當然題目中自帶的坑差點把我誤導了——他給的查詢數字異常的大,之前以為實際達到的數字也是那麽大來著。。。但是很顯然不是,因為最大值的限制是2^N這個尺寸的限制。
於是在這個問題的處理上需要對最大值情況進行特殊判斷。

AC代碼:

#include<iostream>
#include<math.h>
using namespace std;

long long dic[23];
int dp1[3048][11];
int dp[1050000][10];

void init()
{
    long long kk=1;
    for(int i=0;i<23;++i)
    {
        dic[i]=kk;
        kk*=2;
    }dp1[0][0]=1;
    
//    cout<<dic[20]<<endl;
    for
(int i=0;i<11;++i) { for(int j=0;j<dic[i];++j) { int val=j; dp1[val+dic[i]][i+1]+=dp1[j][i]; dp1[val][i+1]+=dp1[j][i]; dp1[abs(val-dic[i])][i+1]+=dp1[j][i]; } } for(int j=0;j<=dic[11];++j) { dp[j][0]=dp1[j][11]; } for(int i=11;i<20;++i) { // cout<<dic[i]<<endl; for(int j=0;j<dic[i];++j) { int val=j; dp[val+dic[i]][i+1-11]+=dp[j][i-11]; dp[val][i+1-11]+=dp[j][i-11]; dp[abs(val-dic[i])][i+1-11]+=dp[j][i-11]; } } } int main() { cin.sync_with_stdio(false); // freopen("indata.in","r",stdin); // freopen("out.txt","w",stdout); // cout<<pow(2,20)<<endl; init(); int t; cin>>t;//cout<<t<<endl; while(t--) { long long a,b; cin>>a>>b; if(b<11) { if(a==0) { cout<<1<<endl; continue; } if(abs(a)>=dic[b])cout<<0<<endl; else cout<<dp1[abs(a)][b]/2<<endl; }else { if(a==0) { cout<<1<<endl; continue; } if(abs(a)>=dic[b])cout<<0<<endl; else cout<<dp[abs(a)][b-11]/2<<endl; } } return 0; }

數據生成器:

#include<bits/stdc++.h>
using namespace std;
int aa=8;
int main()
{
        freopen("indata.in","w",stdout);
        
        long long bb=-pow(2,aa)+1;
        cout<<(long long)pow(2,aa+1)-1<<endl;
        while(bb<pow(2,aa))cout<<bb++<<"   "<<aa<<endl;

}

檢查的代碼:

#include<bits/stdc++.h>
using namespace std;

long long aa[23];
void init()
{
    long long k=1;
    for(int i=0;i<23;++i)
    {
        aa[i]=k;
        k*=3;
    }
}

int main()
{
    init();
        freopen("out.txt","r",stdin);
    long long a,summ=0;
    while(cin>>a)summ+=a;
    cout<<summ<<endl;
    cout<<aa[lower_bound(aa,aa+23,summ)-aa];
}

HOJ 13845 Atomic Computer有向無環圖的動態規劃