題意分析
給出乙個帶權有向圖,要求從節點 $1$ 出發,經過恰好 $t$ 的邊權和,回到節點 $1$ ,求可經過的最大點權和。特別地,經過的邊權和達到部分特殊數時,會有某個點的點權發生改變。
思路分析
樸素演算法
設 $f_$ 表示在節點 $j$ ,經過的邊權和為 $i$ 時可經過的最大點權和。很容易可以得出 dp 方程:
$$f_=\max_(f_)+c_j$$
暴力轉移,點權改變的情況特判修改即可。
優化1可以發現 $w$ 的資料範圍很小,想到用矩陣快速冪優化。
首先拆點,令所有邊邊權都為 $1$ ,然後將所求的點權轉化為邊權:設有 $(u,v,w)\in e$ ,則可以將 $u$ 拆成 $u_0,u_1,...,u_$ ,從 $u_$ 向 $u_i$ 間連一條邊,邊權為 $0$ ,然後從 $u_$ 向 $v$ 連一條邊,邊權為 $c_v$ 。
這樣,問題就轉化為,從節點 $1$ 出發,經過 $t$ 條邊,回到節點 $1$ ,求可經過的最大邊權和,即最長路。
定義乙個廣義矩陣乘法 $ans_=max(a_+b_)$ 。可以證明這個廣義矩陣乘法同樣滿足矩陣乘法的基本運算律,如結合律。
設鄰接矩陣為 $a$ ,可以很容易得出 dp 方程:
$$dp_i=dp_j*a^$$
點權改變的情況怎麼處理?只要先將時間從小到大排序,然後在相鄰的時間之間轉移,轉移後在改變點權在鄰接矩陣中的對應位置修改即可。
優化2分析過後可以發現,因為要求的只是 $dp_}$ ,因此只要保留 $dp$ 矩陣的第一行即可;另外,發現在轉移的時候要多次乘上鄰接矩陣 $a$ 的相同次冪,因此可以先預處理出 $a$ 的 $2$ 的整數次冪。這樣處理之後可以降低一維的複雜度。
#include#include#include#include#define ll long longusing namespace std;
const int n=300;
const ll inf=0xcfcfcfcfcfcfcfcf;
struct node
a[31];
struct fes
b[n];
int n,m,t,k;
int c[n],id[n][5];
ll dp[n];
node max(node x)
return now;
}//廣義矩陣乘法
void maxx(node x)
for(int i=1;i<=n;i++)
dp[i]=now[i];
}//一維乘二維
void pre()
//預處理次冪
void fastpow(int x)
{ for(int i=30;i>=0;i--)
if(x&(1<
被踩計畫 題解 NOI2020 美食家
為什麼叫被踩記錄呢?因為感覺自己之前真的是太菜了,打算把之前聯賽等考過的題目做一做,看看自已以前有多菜,所以取名叫被踩記錄。題目鏈結 發現 t 很大而 n 很小,顯然可以使用矩陣快速冪來優化 dp 但是有幾個問題。首先是 w 並不都為 1 考慮拆點,把乙個點拆成 max w 個點,如果 u 向 v ...
NOI2020 簡要題解
a 首先不難發現乙個暴力動態規劃的做法 記 f 表示第 i 天 當前在第 j 座城市所獲得的最大收益 有轉移方程 f max u cost i extra 發現 w 非常小 考慮拆點。將每個點拆成 w 個點 那麼一共會有至多 5n 個點。接著 考慮矩陣乘法 事實上 將求和運算改為 max 運算 並將...
NOI2020 製作菜品 題解
題意分析 給出 n 個數和 m 個 k 可以某些 k 拆兩個正整數,使得拆後的數可以拼成給出的 n 個數。思路分析 上面的解釋是因為這樣寫比較方便,實際上按照題意應該是用 n 個數拆分拼成 m 個 k 觀察資料範圍,發現有 m geq n 2 的限制和 m geq n 1 的部分分,考慮從這裡切入分...