• luogu4131 [WC2005]友好的生物


    题目

    分析

    part 1

    思维难度挺大的一道题,建议先看看这篇blog及2005国家集训队ysy的解题报告(解题报告的链接在这篇blog里):

    [WC2005]友好的生物

    还有2006陈启峰的论文:一张一弛,解题之道

    part 2

    先由简,不考虑a[k],那么这样直接求怎么求呢?

    直接枚举O(n2k)当然可以,只不过会超时;

    有没有一种方法可以避免一些不必要的枚举呢?

    这道题最大的阻碍就是这个绝对值问题了,因为它只跟两个生物的具体属性的相对大小有关,所以难以确定,必须枚举。

    如果有办法把他给确定了,问题就好解决了。

    part 3

    看看 k 的数据范围,很容易想到可以从k下手;

    抓住绝对值中的‘-’是不变的,也就是说,同一属性两种生物的符号是相反的

    有什么用?(用处可大了)

    说明对被减数取个负,他们的同一属性的符号就一样了呀。

    这样的话,对于每个符号方案,求出每个生物的属性和,再相减不就可以了?

    这个符号下放到每个属性,一共就有2k-1种符号方案(先不考虑第k种)

    你可能会说,这不一定是绝对值

    但是这里面一定包含绝对值,不是绝对值的答案一定会比正确答案小(废话因为是负数)

    part 4

    枚举每一种符号方案(可以用状压01串表示+-),求出里面的最大差就好,这个可以在O(n)的复杂度里求出来;

    边枚举边维护一个min值,用当前值与min值得差更新答案,用当前值更新min值,这样这道题的大致框架就出来了

    part 5

    考虑a[k],它取的是绝对值的相反数,怎么考虑它呢?

    如果它的符号也随机,按照枚举来,这样不能保证a[k]的贡献为负贡献,也不能保证最大差就是正确答案

    那多出来的错误答案便是把a[k]弄成了正贡献;

    要避免这类情况。

    他的特征是小数减大数,我们需要一种方法,既满足最大差就是正确答案,又满足a[k]的性质;

    不考虑a[k]的方法与生物的顺序无关,与某一种属性的大小也无关,但是a[k]就明显与大小有关了

    a[k]必须保证是小数减大数,而其他的属性随意,这样就可以保证最大差就是正确答案;

    既然a[k]与大小有关,不如就按照a[k]的大小确定加减,a[k]小的为被减数,而a[k]的符号确定为+。

    这样做能否保证上述方法的正确性呢?

    这样做,保证了第k种属性对答案的贡献为负,前面的符号仍然是枚举符号,而a[k]的符号确定,这样再求最大差,仍然是满足正确性

    不如就按照a[k]的大小排序,保证a[k]大的在前面,只考虑减去比a[k]它大的生物,这样就可以按照part 4的方法在O(n)的时间中求出最大差

    题解:

     

    代码

      1 /***************************
      2 User:Mandy.H.Y
      3 Language:c++
      4 Problem:species
      5 Algorithm:
      6 Score:
      7 ***************************/
      8 #include<bits/stdc++.h>
      9 
     10 using namespace std;
     11 
     12 const int maxn = 1e5 + 5;
     13 const int maxk = 6;
     14 
     15 int n,k,cur,ans,ans1,ans2,curid;
     16 int c[maxk];
     17 
     18 struct Node{
     19     int a[10],id;
     20     bool operator <(const Node &b)const {
     21         return a[k] > b.a[k];
     22     }
     23 }p[maxn]; 
     24 
     25 template<class T>inline void read(T &x){
     26     x = 0;bool flag = 0;char ch = getchar();
     27     while(!isdigit(ch)) flag |= ch == '-',ch = getchar();
     28     while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48),ch = getchar();
     29     if(flag) x = -x;
     30 }
     31 
     32 template<class T>void putch(const T x){
     33     if(x > 9) putch(x / 10);
     34     putchar(x % 10 | 48);
     35 }
     36 
     37 template<class T>void put(const T x){
     38     if(x < 0) putchar('-'),putch(-x);
     39     else putch(x);
     40 }
     41 
     42 void file(){
     43     freopen("species.in","r",stdin);
     44     freopen("species.out","w",stdout);
     45 }
     46 
     47 void readdata(){
     48     read(n);read(k);
     49     for(int i = 1;i <= k; ++ i) read(c[i]);
     50     
     51     for(int i = 1;i <= n; ++ i){
     52         p[i].id = i;
     53         for(int j = 1;j <= k; ++ j){
     54             read(p[i].a[j]);
     55             p[i].a[j] *= c[j];                    
     56         }
     57     }
     58 } 
     59 
     60 void work(){
     61     sort(p + 1,p + n + 1);
     62     ans = -2e9;
     63     for(int i = 0;i < (1 << (k - 1)); ++ i){
     64         
     65         cur = p[1].a[k];curid = p[1].id;
     66         for(int l = 1;l <= k - 1 ; ++ l){
     67             if(i & (1 << (l - 1))) cur += p[1].a[l];
     68             else cur -= p[1].a[l];
     69         }
     70         
     71         for(int j = 2;j <= n; ++ j){
     72             int now = p[j].a[k];
     73             for(int l = 1;l <= k - 1 ; ++ l){
     74                 if(i & (1 << (l - 1))) now += p[j].a[l];
     75                 else now -= p[j].a[l];
     76             } 
     77             if(now - cur > ans){
     78                 ans = now - cur;
     79                 ans1 = curid;
     80                 ans2 = p[j].id;
     81             }
     82             
     83             if(now < cur){
     84                 cur = now;
     85                 curid = p[j].id;
     86             }
     87         }
     88     }
     89     put(ans1);putchar(' ');put(ans2);putchar('
    ');
     90     put(ans);
     91  
     92 }
     93 
     94 
     95 int main(){
     96 //    file();
     97     readdata();
     98     work(); 
     99     return 0;
    100 }
    View Code
    非做顽石不可,哪管他敬仰暗唾
  • 相关阅读:
    Luogu 1514 引水入城
    HDU 2196 Computer
    CF460C Present
    初等数论整理
    2019UMS培训day6解题报告
    2019UMS培训day5解题报告
    2019UMS培训day3解题报告
    Luogu 1731 生日蛋糕
    JavaWeb之ServletContext域对象
    c3p0连接池
  • 原文地址:https://www.cnblogs.com/Mandy-H-Y/p/11410284.html
Copyright © 2020-2023  润新知