Luogu4131 WC2005 友好的生物 状压DP
Posted itst
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Luogu4131 WC2005 友好的生物 状压DP相关的知识,希望对你有一定的参考价值。
首先$C_i$是没有意义的,因为可以直接让$d_i imes= C_i$,答案也是一样的
所以我们现在考虑求$(sum_{i=1}^{K-1} |d_{p,i}-d_{q,i}|) - |d_{p,K} - d_{q,K}|$的最大值
这个绝对值好烦人啊qaq
我们考虑如何消去这个绝对值
先抛开第$K$项,假设我们要计算$sum_{i=1}^{K-1} |d_{p,i}-d_{q,i}|$的最大值
可以发现$sum_{i=1}^{K-1} |d_{p,i}-d_{q,i}| = max(sum_{i=1}^{K-1} (d_{p,i}-d_{q,i}) imes (-1)^{a_i})=max(sum_{i=1}^{K-1} d_{p,i} imes (-1)^{a_i} + d_{q,i} imes (-1)^{a_i + 1})$
其中$0 leq a_i leq 1$且取遍所有情况
那么我们可以设$dp_j$表示$a_i$状压成二进制表示为$j$时的$sum_{i=1}^{K-1} d_{p,i} imes (-1)^{a_i}$的最大值,$ind_j$表示$dp_j$取到最大值时的$p$值,转移也比较方便了。
最后我们考虑第$K$维的影响,我们不妨按照第$K$维从小到大排序,那么$dp_j$表示$a_i$状压成二进制表示为$j$时的$sum_{i=1}^{K-1} d_{p,i} imes (-1)^{a_i} + d_{K,i}$的最大值,最后统计答案时再减去当前的$d_K$值就可以了
1 #include<bits/stdc++.h> 2 //This code is written by Itst 3 using namespace std; 4 5 inline int read(){ 6 int a = 0; 7 char c = getchar(); 8 bool f = 0; 9 while(!isdigit(c)){ 10 if(c == ‘-‘) 11 f = 1; 12 c = getchar(); 13 } 14 while(isdigit(c)){ 15 a = (a << 3) + (a << 1) + (c ^ ‘0‘); 16 c = getchar(); 17 } 18 return f ? -a : a; 19 } 20 21 const int MAXN = 100010; 22 int dp[16] , dir[16] , C[5]; 23 int N , K , ans , ind1 , ind2; 24 struct ani{ 25 int val[5] , ind; 26 bool operator <(const ani a)const{ 27 return val[K - 1] < a.val[K - 1]; 28 } 29 }now[MAXN]; 30 31 inline int calc(int d , int type){ 32 int sum = 0; 33 for(int i = 0 ; i < K - 1 ; ++i) 34 sum += (type & (1 << i) ? 1 : -1) * now[d].val[i]; 35 return sum; 36 } 37 38 int main(){ 39 #ifndef ONLINE_JUDGE 40 freopen("in" , "r" , stdin); 41 //freopen("out" , "w" , stdout); 42 #endif 43 N = read(); 44 K = read(); 45 for(int i = 0 ; i < K ; ++i) 46 C[i] = read(); 47 for(int i = 1 ; i <= N ; ++i){ 48 for(int j = 0 ; j < K ; ++j) 49 now[i].val[j] = read() * C[j]; 50 now[i].ind = i; 51 } 52 sort(now + 1 , now + N + 1); 53 for(int i = 0 ; i < 1 << (K - 1) ; ++i){ 54 dir[i] = now[1].ind; 55 dp[i] = calc(1 , i) + now[1].val[K - 1]; 56 } 57 for(int i = 2 ; i <= N ; ++i){ 58 for(int j = 0 ; j < 1 << (K - 1) ; ++j){ 59 int t = calc(i , j) , d = (1 << (K - 1)) - 1 - j; 60 if(t + dp[d] - now[i].val[K - 1] > ans){ 61 ans = t + dp[d] - now[i].val[K - 1]; 62 ind1 = now[i].ind; 63 ind2 = dir[d]; 64 } 65 } 66 for(int j = 0 ; j < 1 << (K - 1) ; ++j) 67 if(dp[j] < calc(i , j) + now[i].val[K - 1]){ 68 dp[j] = calc(i , j) + now[i].val[K - 1]; 69 dir[j] = now[i].ind; 70 } 71 } 72 cout << ind1 << ‘ ‘ << ind2 << endl << ans; 73 return 0; 74 }
以上是关于Luogu4131 WC2005 友好的生物 状压DP的主要内容,如果未能解决你的问题,请参考以下文章
Luogu4221 WC2018州区划分(状压dp+FWT)