• 【FZU2178】礼物分配


    题意

      在双胞胎兄弟Eric与R.W的生日会上,他们共收到了N个礼物,生日过后他们决定分配这N个礼物(numv+numw=N)。对于每个礼物他们俩有着各自心中的价值vi和wi,他们要求各自分到的礼物数目|numv-numw|<=1,并且各自所衡量的礼物价值的差值|sumv-sumw|尽可能小,现在他们想知道最小的差值是多少。

    分析

      这是中途相遇法的模板题

      每个礼物要么属于Eric,要么属于R.W,所以如果暴力的话是2^30,显然会超。

      使用中途相遇法可以将复杂度降到2^15左右,很是神奇。

     1. 先将N个礼物分成两份,第一份有n/2个礼物,第二份有n-n/2个礼物。

     2. 然后枚举第一份中有哪些属于Eric,哪些属于R.W。cnt来记录第一份中Eric的礼物数目,sum1是第一份中Eric的礼物价值和,sum2是R.W的礼物价值和。然后用一个vector,把每个sum1-sum2都加到下标为cnt的vector中。

     3.  用类似的方法,枚举第二份中哪些属于Eric,哪些属于R.W。sum1,sum2,cnt的含义相同。然后在下标为n-n/2-cnt的vector中找和这个sum1-sum2相加最小的值,然后判断是否要更新ans。

      就是这样,用这个题来学中途相遇法了。。。步骤3中的小细节还是比较神奇的。

      下面是代码

      

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <vector>
     6 #include <map>
     7 
     8 using namespace std;
     9 typedef long long LL;
    10 
    11 const int maxn=35;
    12 const int INF=2147000000;
    13 int T,n;
    14 int v[maxn],w[maxn];
    15 vector<int>V[maxn];
    16 
    17 int main(){
    18     scanf("%d",&T);
    19     for(int t=1;t<=T;t++){
    20         scanf("%d",&n);
    21         for(int i=0;i<=n;i++)V[i].clear();
    22         for(int i=1;i<=n;i++)
    23             scanf("%d",&v[i]);
    24         for(int i=1;i<=n;i++)
    25             scanf("%d",&w[i]);
    26         int n1,n2;
    27         n1=n/2,n2=n-n1;
    28         int cnt;
    29         LL sum1,sum2;
    30         for(int i=0;i<(1<<n1);i++){
    31             cnt=0,sum1=0,sum2=0;
    32             for(int j=0;j<n1;j++){
    33                 if(i&(1<<j)){
    34                     cnt++;
    35                     sum1+=v[j+1];
    36                 }else
    37                     sum2+=w[j+1];
    38             }
    39             V[cnt].push_back(sum1-sum2);
    40         }
    41 
    42         for(int i=0;i<=n1;i++){
    43             sort(V[i].begin(),V[i].end());
    44             V[i].erase(unique(V[i].begin(),V[i].end()),V[i].end());
    45         }
    46 
    47 
    48         int ans=INF;
    49         for(int i=0;i<(1<<n2);i++){
    50             cnt=0,sum1=0,sum2=0;
    51             for(int j=0;j<n2;j++){
    52                 if(i&(1<<j)){
    53                     cnt++;
    54                     sum1+=v[n1+j+1];
    55                 }else{
    56                     sum2+=w[n1+j+1];
    57                 }
    58             }
    59             int cnt1,SUM;
    60             cnt1=n2-cnt,SUM=sum1-sum2;
    61             vector<int>::iterator it;
    62             it=lower_bound(V[cnt1].begin(),V[cnt1].end(),-SUM);
    63             if(it!=V[cnt1].end()&&abs(*it+SUM)<ans){
    64                 ans=abs(*it+SUM);
    65             }
    66             if(it!=V[cnt1].begin()){
    67                 it--;
    68                 if(abs(*it+SUM)<ans)
    69                     ans=abs(*it+SUM);
    70             }
    71         }
    72         printf("%d
    ",ans);
    73     }
    74 return 0;
    75 }
    View Code
  • 相关阅读:
    iOS 的 Block 的使用
    iOS 的Could not find Developer Disk Image错误
    iOS 面试
    iOS 开发工具——统计Crash的工具Crashlytics
    iOS 的 Foundation 框架
    iOS 页面之间的传值总结
    iOS 常用四种数据存储方式
    iOS 的 Delegate Notification KVO
    iOS 的 Delegate 设计模式 及 自定义代理
    iOS 的 NSNumber(对基本数据类型) & NSValue(对结构体) 的装箱
  • 原文地址:https://www.cnblogs.com/LQLlulu/p/9017399.html
Copyright © 2020-2023  润新知