牛客訓練營G 機械人(狀壓dp 記憶化搜尋)

2021-10-20 10:44:04 字數 1505 閱讀 3529

n個機械人,每個機械人會讀入乙個x,並返回ax+b。現在有乙個x,想讓你合理安排機械人順序,使得最終返回得到的x盡可能大,輸出最大值。(1<=n,x,ai,bi<=20)

給的範圍很小才20,那麼就可以考慮到狀壓dp

dp[i][t]表示第i次迴圈在狀態t的情況下出的最大值。t在二進位制狀態下1的位置表示該位置的機械人已經取過,比如5(101)表示1和3位置的機械人已經使用過。所以第i次迴圈中就列舉狀態t中0的位置j,然後使用該機械人j,那麼使用過機械人j之後狀態就變成了t2=t|(1《然後還可以進行記憶化搜尋,當然啦,其實原理差不多,但是畢竟是記憶化搜尋,少跑好多內容,時間上會節省好多,具體看**。

需要注意的是最大值是20^20次,爆longlong了,這裡使用了__int128以及他的輸出函式。

狀壓dp

#includeusing namespace std;

#define io cin.tie(0);ios::sync_with_stdio(false);

#define ok(x, y) x >= 1 && x <= n && y >= 1 && y <= m

#define debug(x) cout<<#x<<"="<#define mk make_pair

#define ll long long

#define ull unsigned long long

#define lb long double

#define rs p<<1|1

#define ls p<<1

#define eps 1e-6

#define pi acos(-1)

const int maxn = 2e5 + 5;

const int mod = 998244353;

const int inf = 0x3f3f3f3f;

const int bas = 2333;

inline ll read()

while(c>='0'&&c<='9')

return f*p;

}void print(__int128 x)

if (x>9) print(x/10);

putchar('0'+x%10);

}__int128 dp[25][1<<20];

int a[25], b[25];

void solve()

while(c>='0'&&c<='9')

return f*p;

}void print(__int128 x)

if (x>9) print(x/10);

putchar('0'+x%10);

}__int128 dp[1<<20];

int a[25], b[25], n;

__int128 dfs(int x)

return dp[x];

}void solve()

int main()

計蒜客 灌溉機械人(狀壓DP)

灌溉機械人 include include using namespace std const int max n 100 const int max m 10 int state max n 1 i行狀態 int dp max n 1 1 max m 1 max m i行狀態為j i 1行狀態為k...

牛客寒假演算法基礎訓練營1 G

這道題的題解講的非常好了已經,對於1 n數的排列子區間 l,r 使得區間中的數滿足連續的條件為 r l max a l r min a l r l,r為下標 既然要使 l,r 為萌區間,那麼就要找到這個區間內的最大值mx與最小值mn,判斷是否滿足條件 若不滿足條件,那麼需要將 mn,mx 缺少的數字...

牛客訓練營1 C(2 0)

題目描述 小a正在玩一款星際探索遊戲,小a需要駕駛著飛船從1號星球出發前往n號星球。其中每個星球有乙個能量指數p。星球i能到達星球j當且僅當pi pj。同時小a的飛船還有乙個耐久度t,初始時為1號點的能量指數,若小a前往星球j,那麼飛船的耐久度會變為t pj 即t異或pj 小a想知道到達n號星球時耐...