初涉狀態壓縮 在更

2022-05-20 03:57:09 字數 2797 閱讀 5578

一直都只會二進位制的狀態壓縮……

狀態壓縮,顧名思義,就是把乙個大的狀態壓成相對來說記憶體更小的東西(通常來說是乙個int數字)。而這樣做又有什麼好處呢?就是當狀態的複製量很大,但修改次數相對較小時佔優勢。(試想一下如果不用回溯,那麼dfs時每一層棧空間都帶乙個vis陣列……)

題目描述

一張 n 個點 m 條有向邊的圖上,有 q 個配送需求,需求的描述形式為 (si,ti,li,ri),即需要從點 s_i​​ 送到 t_i, 在時刻 l_i​​ 之後(包括 l_i)可以在 s_i​​ 領取貨物,需要在時刻 r_i​​ 之前(包括 r_i)送達 t_i ,每個任務只需完成一次。

圖上的每一條邊均有邊權,權值代表通過這條邊消耗的時間。在時刻 0 有乙個工作人員在點 1 上,求他最多能完成多少個配送任務。

在整個過程中,可以認為領貨跟交貨都是不消耗時間的,時間只花費在路程上。當然在乙個點逗留也是允許的。

輸入格式

第一行,三個正整數 n,m,q(2≤n≤20,1≤m≤400,1≤q≤10)。

接下來 m 行,每行三個正整數 ui,vi,ci(1≤ui,vi≤n,1≤ci≤20000),表示有一條從 ui​​ 到 vi​​ 耗時為 ci 的有向邊。

接下來 q 行,每行四個正整數 si,ti,li,ri(1≤si,ti≤n,1≤li≤ri≤10^6),描述乙個配送任務。

輸出格式

乙個整數,表示最多能完成的任務數量。

記憶體限制:32 mib時間限制:200 ms標準輸入輸出

題目分析

我們首先可以發現n和q都是很小的,又注意到這題的時空限制很不尋常,於是可以大膽結合題意猜測一些想法。

其實沒什麼好猜的我直接步入正題講狀態壓縮算了就不講我那zz的dfs了

對於每乙個送貨任務來說,一共只有三種情況:0.貨還沒取;1.取貨了沒送到;2.已經送到了。

於是考慮狀壓dfs。

狀壓怎麼壓呢?形象一些就是一串長為q的三進製數,例如(021)(q=3),代表第一單貨未取;第二單貨已送到;第三單貨正在配送。

於是用乙個int型別的state以十進位制的方式存放狀態。十進位制?那麼怎麼提取各個狀態呢?如同二進位制狀壓一樣,我們需要預處理三的各次冪。正是因為狀態壓縮這樣的特性,所以它適用於需要頻繁複製狀態,而提取狀態相對容易的情況。

由於我第一次接觸這種三進製狀壓時候,對於一些從未見過的操作頗有感觸,那麼就在**裡注釋吧。

hint:每一次可以接很多單(在路上跑的時候可以一次拿很多外賣)

**:

1 #include2

const

int maxn = 21

;  //n的最大值(一共多少點)

3const

int max3 = 60003

;//送貨狀態轉為十進位制數後的最大值,用於最優性剪枝45

struct

node

69 node(int a, int b, int c, int

d):s(a),t(b),l(c),r(d) {}

10}a[maxn];        //存送外賣每一單的需求

11int

ans,n,m,q;

12int f[maxn][max3],dis[maxn][maxn],base

[maxn];      //base是3的各次冪,用於提取狀態

1314

intread()

1523

void dfs(int now, int state, int

times)

//now:現在在now這個點上,注意是送貨地圖的點

//state:現在所有送貨的狀態

//times:現在已經花費的時間

2430

if (f[now][state] < times) return

;  //最優性剪枝

31 f[now][state] =times;

32int cpy = state, cnt = 0;33

while

(cpy)

34//提取當前狀態中有多少外賣已經送到了

38if (ans < cnt) ans =cnt;

39for (int i=1; i<=q; i++)        //接下去遍歷每一單貨物,考慮dfs的後繼

40else

if (state/base[i-1]%3==1 && times+dis[now][a[i].t] <=a[i].r)

45 dfs(a[i].t, state, times+dis[now][a[i].t]); //如果這一單已經在配送過程中了,那麼現在去配送這一單46}

47}48int

main()

4958

for (int k=1; k<=n; k++)

5966

for (int i=1; i<=q; i++)

6771

base[0] = 1

;                  //預處理三的冪次(3^0,3^1,3^2……)

72for (int i=1; i<=q; i++)

73base[i] = base[i-1]*3

;74 dfs(1, 0, 0

);75 printf("

%d\n

",ans);

76return0;

77 }

另,待更,炮兵陣地

初涉彙編《三》

在彙編 二 中我的說的問題,在這就不做回答了,因為乙個暫存器的來儲存資料肯定不夠用,因此,這些暫存器就可以提供空間。好了,這個彙編學習畢竟是我對彙編的個人的學習問題。現在我來說說彙編中後面的幾個標誌暫存器。標誌暫存器總共有9個,分別是cf,pf,af,zf,sf,tf,if,df,of 詳細解答,看...

初涉字尾陣列

以poj 1743為例。模板中的基數排序基於前向星。詳細證明過程詳見 演算法合集之 字尾陣列 處理字串的有力工具 非常不錯的一篇 include include include include include include include include include include inclu...

React 初涉總結

來新公司開始用 react 已經兩個多月了,當然之前我對 react 也不是一無所知的,對 react 的基礎語法 jsx virtual dom 都是有一定的了解。之前用過 angular vue,對元件化開發都掌握的很熟練了,但 react 與 angular vue 還是有較大差異的,在使用 ...