ZJOI2010 貪吃的老鼠

2022-10-08 23:36:23 字數 2750 閱讀 8782

點這裡看題目。

注意到,這個題目的特點之一是時間是連續的。這意味著我們可以單純地關注數值而不太需要關心具體的時間。比如,乙隻老鼠在長度為 \(t\) 的時間段內,想要吃下 \(x_k\) 的第 \(k\) 塊乳酪,則這一點能否做到,完全等價於 \(\sum_kx_k\) 是否 \(\le ts\)。

想了好久如何轉化將時間和乳酪互相轉化,沒想到被題解直接一下子解決了

不過老鼠能吃哪些乳酪還是需要考慮的問題。這很簡單,直接將時間離散成時間段即可。每乙個時間段內老鼠能吃的乳酪是不會變的。在乙個確定的時間段內,我們可以直接將老鼠作為網路流的結點來建圖嗎?似乎不可以,我們必須保證乙個乳酪被乙隻老鼠吃,但這樣會導致乳酪選中乙個老鼠的子集——這似乎也是性質之一,怎麼用呢?

如果苛刻一點,我們可能會要求一種拆分方法,使得其中任何乙個子集選出來都可以恰好對應到乙隻老鼠。顯然這是不可能的,這必然要求 \(n\) 為 \(2\) 的乙個整冪。不過,我們可以退而求其次,利用實數流很容易進行調整的性質,我們也許只需要保證老鼠可以被對應到某些子集即可?這是易於實現的,差分老鼠的速度即可。

進一步地,差分之後,我們可以建立從乳酪指向老鼠的邊。如何確定老鼠的「容量」?差分之後,第 \(k\) 快的老鼠的差分值實際上會被算到 \(m-k+1\) 次,將這個係數算到容量裡面即可。

至於這個東西怎麼滿足題目要求的,請參考他人部落格

小結:注意某些變數的特點,這裡的連續時間就是乙個很強的條件。

注意到了反而不會用

差分想法很重要,但怎麼想到差分更重要。在這裡,主要是子集選取這樣乙個結構給了我們啟發。

#include #include #include #define rep( i, a, b ) for( int i = (a) ; i <= (b) ; i ++ )

#define per( i, a, b ) for( int i = (a) ; i >= (b) ; i -- )

const int inf = 1e9;

const double eps = 1e-7, inf = 1e18;

const int maxn = 1e5 + 5, maxe = 1e6 + 5, maxn = 100;

templatevoid read( _t &x )

while( '0' <= s && s <= '9' )

if( f ) x = -x;

}templatevoid write( _t x )

template_t min( const _t a, const _t b )

struct edge graph[maxe << 1];

int q[maxn];

int dep[maxn], cur[maxn];

int head[maxn], cnt = 1, ntot = 0;

double tim[maxn]; int tot = 0;

int p[maxn], r[maxn], d[maxn], s[maxn];

int n, m;

inline int sgn( const double &x )

inline void addedge( const int from, const int to, const double c )

inline void adde( const int from, const int to, const double c )

bool bfs( const int s, const int t )

return dep[t] < inf;

}double dfs( const int u, const double lin, const int t )

}if( sgn( used - lin ) ) dep[u] = inf;

return used;

}double dinic( const int s, const int t )

return flow;

}#define id( t, x ) ( ( (t) - 1 ) * m + (x) + n )

bool chk( const double t )

std :: sort( tim + 1, tim + 1 + tot );

tot = std :: unique( tim + 1, tim + 1 + tot ) - tim - 1;

ntot = n + m * ( tot - 1 );

const int s = ++ ntot, t = ++ ntot;

rep( i, 1, ntot ) head[i] = 0;

rep( i, 1, n )

rep( j, 1, tot - 1 ) rep( k, 1, m )

adde( id( j, k ), t, ( tim[j + 1] - tim[j] ) * s[k] * ( m - k + 1 ) );

double su = 0;

rep( i, 1, n ) su += p[i];

return ! sgn( su - dinic( s, t ) );

}int main()

printf( "%g\n", l );

}return 0;

}

ZJOI2010 貪吃的老鼠

傳送門 to luogu 注意到老鼠的吃麵包時間是實數範圍內的,所以我們大膽地說 x1 x2 x3 xn ts i forall x 1 x 2 x 3 cdots x n le ts i x1 x 2 x 3 xn tsi 第 i ii 個老鼠可以做到,在 t tt 的時間內,將第 j jj 個麵...

ZJOI2010 貪吃的老鼠

p2570 zjoi2010 貪吃的老鼠 在ta的部落格檢視 顯然二分,最大流判定 要滿足兩個條件 1 在任一時刻,乙隻老鼠最多可以吃一塊乳酪 2 在任一時刻,一塊乳酪最多被乙隻老鼠吃。先按照乳酪的邊界進行離散化,變成num個塊,就可以知道每個時間有哪些乳酪了 把每個老鼠拆成num個點,初步 每個老...

ZJOI2010 數字計數

題目描述 給定兩個正整數a和b,求在 a,b 中的所有整數中,每個數碼 digit 各出現了多少次。輸入格式 輸入檔案中僅包含一行兩個整數a b,含義如上所述。輸出格式 輸出檔案中包含一行10個整數,分別表示0 9在 a,b 現了多少次。輸入輸出樣例 輸入 1 1 99 輸出 1 9 20 20 2...