填坑,史前巨坑。
題意:對於一張圖,確定乙個點為根,構建乙個生成樹。求代價最小值。
代價的定義:「樹中每一條邊的權值與較淺點深度的乘積」之和。
考場上沒有想清楚就草草碼了乙個prim然後交了,但是因為你代價和深度有關,所以貪心地prim是錯誤的。
因為 $n$ 很小,這應當引導我們想到狀壓。(套路)
答案與深度有關,所以我們可以令 $f[i][s]$ 為最深點深度為 $i$,已選點的集合為 $s$ 時的最小答案。
列舉 $p$ 為 $s$ 的補集的子集,那麼
$$f[i][s|p]=min(f[i-1][s]+cost[p])$$
狀壓可以把集合壓成二進位制數。(套路 again)
列舉集合補集的子集怎麼做?
可以用樹狀陣列**現的 $lowbit(i)=i\&(-i)$。(小技巧)
如何求 $cost$ 呢?同樣用 $lowbit$。
然後我們就可以歡快的轉移狀態了。特判一下 $n=1$。
**:
#include#include#include#include#include#include#define reg register
#define cmin(_,__) ((_)>(__)?(_)=(__),1:0)
#define cmax(_,__) ((_)<(__)?(_)=(__),1:0)
#define dmin(_,__) ((_)<(__)?(_):(__))
#define dmax(_,__) ((_)>(__)?(_):(__))
#define abs(_) ((_)>0?(_):-(_))
#define lowbit(_) ((_)&-(_))
using namespace std;
const long long inf=1ll<<29;
int n,m,tot,pos[15],two[5005],used[5005];
long long f[15][5005],map[15][15],res=inf,v[15],g[5005];
int main()
for(reg int i=0;ifor(reg int j=0;jmap[i][j]=inf;
for(reg int i=1,u,v,w;i<=m;i++)
for(reg int i=0;itwo[1
for(reg int s=0;s<(1
for(reg int i=0;if[0][1
g[0]=used[0]=0;
for(reg int j=1;j<(1<}
}for(reg int i=1;i<=n;i++)
cmin(res,f[i][(1
return 0;
}
2013NOIP D1 T2 火柴排隊
題目點這裡 題目大意 有兩列火柴,給出他們的根數和他們對應的長度ai,bi,並且規定距離為 解題思路 怎麼使距離最小?哈哈哈哈,是在兩個佇列裡面的火柴相對應 a集合火柴中第i小對應b集合中第i小 將兩個集合排序 為了讓ab相對應 因為排好序a,b是最小的,所以a下標與b下標就要對應 然後按照a去處理...
NOIP 模擬題 T2 寶藏(樹形dp)
題解 樹形dp 其實這道題說起來很簡單,用四個陣列 d1 d0 u0 u1分別表示從當前點向下更新,不返回 從當前點向下更新再回到當前點 從當前點向上更新回到當前點 從當前點向上更新不返回。用兩遍dfs求出這四個陣列 實現起來細節會比較多,耐心處理 include include include d...
T2 監考老師 題解
第二題,他並不是多難的演算法。甚至連搜尋都不用,他的題目要求和資料斷定了他第二題的地位。在乙個大試場裡,有 n 行 m 列的考生,小王和眾多同學正在考試,這時,有一部分考生 作弊,當然,監考老師能發現他們。但是只有乙個監考老師,他由於高度近視,只能發現與 他同行同列的作弊者,而且由於監考老師年老體弱...