Loading

模拟33—「Hunter·Defence·Connect」

Hunter

正解很简洁,然而没想到。
期望的线性性展开题目所求,可以发现就是其他猎人死在他前面的概率求和。
然后因为要求他什么时候死所以再加一个1。
其他猎人死在他前面的概率就是 \(\frac{W_i}{W_1+W_i}\)

期望的题无非就是dp或者线性展开后dp或直接求
dp实在想不出来怎么转移可以考虑直接求

Defence

考场上想到转化和线段树合并了,也调试成功了,但是有一个小细节没注意到。
就是中间最长的长度还要和左边最长的长度+右边最长的长度去取max。
我真的是sb,其实对拍的时候写暴力的时候一定要多想点,不要按着正解的思路去写暴力,否则只能检查你线段树写没写对,不能检查你这题写没写对。

Connect

考场想了个乱搞
就是状压出来一个1~n的联通块,在联通块内求最大生成树。
再用dfs染色出来其他联通块。
其他联通块随便连边,和状压联通块每个其他联通块只能和上面的一个点连边。

虽然具体思路不太对,但是性质还是对的。
这种图论题一定要多画画,多画几个例子就知道有什么性质了。

正解是利用上面的性质打了个状压dp

状态定义 \(f_{s,u}\) 表示点集为 s ,当前考虑的链的末端为 u 的时候的最小代价。

按照上面的性质,有两个操作

  1. 加进去一个点v,把v变成链的末尾,要求是v和s的除了(u,v)的所有连边都要去掉

\[\large f_{s,u}+calc(s,v)\rightarrow f_{s|\{v\},v} \]

  1. 加进去一坨点,对应和状压联通块上最多一个点连边

\[\large f_{s,u}+calc(s,\{l\})\rightarrow f_{s|\{l\},u} \]

然后复杂度是 \(O(3^nnm)\)的,并不对,所以需要把 \(calc\)预处理出来,复杂度就变成 \(O(3^nn^2)\)

第一次学到枚举子集的正确打开方式

	for( R T = S ; T ; T = ( ( T - 1 ) & S ) )
		//T是S的子集

粘一个代码方便理解。

code
#include <cstdio>
#include <bitset>
#include <cstring>
#include <iostream>
#include <assert.h>
#include <algorithm>
#define R register int
#define scanf Ruusupuu = scanf
#define freopen rsp_5u = freopen

int Ruusupuu ;
FILE * rsp_5u ;

using namespace std ;
typedef long long L ;
typedef double D ;
const int N = 1e5 + 10 ;

inline int read(){
	int w = 0 ; bool fg = 0 ; char ch = getchar() ;
	while( ch < '0' || ch > '9' ) fg |= ( ch == '-' ) , ch = getchar() ;
	while( ch >= '0' && ch <= '9' ) w = ( w << 1 ) + ( w << 3 ) + ( ch - '0' ) , ch = getchar() ;
	return fg ? -w : w ; 
}

int n , m , x , y , z , f [1 << 16][16] , lg [1 << 21] , ans = 1e9 , calcs [1 << 16][16] , Y [1 << 16][16] ;
int fr [N << 1] , to [N << 1] , net [N << 1] , head [N] , cnt = 1 , w [N] ; 

#define add( f , t ) fr [++ cnt] = f , to [cnt] = t , net [cnt] = head [f] , head [f] = cnt , w [cnt] = z

void sc(){
	n = read() , m = read() , memset( head , -1 , sizeof( head ) ) ;
	for( R i = 1 ; i <= m ; i ++ ) x = read() , y = read() , z = read() , add( x , y ) , add( y , x ) ;
}

inline void debug( int x ){ cout << bitset<10>(x) << endl ; }
inline int lb( int x ){ return x & -x ; }

inline int calc( int x , int p ){
	int ans = 0 ;
	for( R i = head [p] ; ~i ; i = net [i] )
		if( ( 1 << ( to [i] - 1 ) ) & x ) ans += w [i] ;
	return ans ;
}

inline int Calc( int x , int p ){
	int ans = 0 ;
	while( p ){
		int j = lg [lb( p )] + 1 ;
		ans += calcs [x][j] ;
		p -= lb( p ) ;
	} 
	return ans ;
}

void work(){
	for( R i = 1 ; i < ( 1 << n ) ; i ++ )
		for( R j = 1 ; j <= n ; j ++ )
			calcs [i][j] = calc( i , j ) ;

	for( R i = 1 ; i <= n ; i ++ ){
		for( R j = head [i] ; ~j ; j = net [j] ){
			for( R k = 1 ; k < ( 1 << n ) ; k ++ )
				if( ( 1 << ( to [j] - 1 ) ) & k ) Y [k][i] += w [j] ;
		}
	} 
			
	lg [0] = -1 ;
	for( R i = 1 ; i < ( 1 << n ) ; i ++ ) lg [i] = lg [i / 2] + 1 ; 
	memset( f , 0x3f , sizeof( f ) ) , f [1][1] = 0 ;
	for( R i = 1 ; i < ( 1 << n ) ; i ++ ){
		R j = i , p = ( i ^ ( ( 1 << n ) - 1 ) ) ; 
		while( j ){
			R k = lg [lb( j )] + 1 ;
			for( R l = head [k] ; ~l ; l = net [l] )
				if( i & ( 1 << ( to [l] - 1 ) ) ) continue ;
				else f [i | ( 1 << ( to [l] - 1 ) )][to [l]] = min( f [i | ( 1 << ( to [l] - 1 ) )][to [l]] , f [i][k] + calcs[i][to [l]] - w [l] ) ;
			
			for( R l = p ; l ; l = ( ( l - 1 ) & p ) )
				f [i | l][k] = min( f [i | l][k] , f [i][k] + Calc( i , l ) - Y [l][k] ) ;
			j -= lb( j ) ;
		}
	} printf( "%d\n" , f [( 1 << n ) - 1][n] ) ; 
}

signed main(){
	sc() ;
	work() ;
	return 0 ;
}

总结

这场又炸了,原因如下

  1. T1没有复习OI宝典,导致忘记取模,挂了35pts
  2. T2被很水的样例骗了,差一个小细节没想,导致错误的std拍错误的程序,要是想想细节就 9->100。
  3. T3就差几行没打完(虽然是假的,还有一个细节不太对),80->0

225->19

亿些收获

  1. T1我认为能推出来,然而还是高估了自己,主要是卡在状态定义上没出来,一直想推个柿子,没想到概率和期望常用套路线性展开,自己概率和期望还是太弱。
  2. T1不知道为什么dfs和状压都打了,浪费了写完T3的时间,以后状压写的还是要自信点。
  3. T2细节想少了,没想到左右还能有贡献,所以挂没了,这种题必须要先理解完,如果样例水,一定要多想点。
  4. T3乱搞考场想的,虽然我知道这么麻烦一看就不是正解,但是还是打了,实际上也不是很难调,分数也不是很少,其实这种乱到一定下程度上的乱搞可以一打,因为出题人可能都想不到你能搞得这么乱。
  5. T3正解很神仙,各种dp只要状态定义一麻烦(就是不能直接从题里面看出来的那种),我几乎就想不到,其实也没往dp想,dp巨弱,考场上剩出来时间可以考虑给不以为是dp的题随便乱搞几个dp定义,没准会有额外的收获。
  6. 这场虽然没打出来多少,但是推了几个性质,确实推性质,转化题意比较重要,只有思考才能进步。
posted @ 2021-08-08 17:47  Soresen  阅读(91)  评论(1)    收藏  举报