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的主要内容,如果未能解决你的问题,请参考以下文章

友好的生物(状压dp)

Luogu4221 WC2018州区划分(状压dp+FWT)

题解Luogu P4121 [WC2005]双面棋盘

Luogu P1896 [SCOI2005]互不侵犯

BZOJ 25952595: [Wc2008]游览计划 (状压DP+spfa,斯坦纳树?)

BZOJ2595: [Wc2008]游览计划(斯坦纳树,状压DP)