zoukankan      html  css  js  c++  java
  • FZU 11月月赛D题:双向搜索+二分

    /*

    双向搜索感觉是个不错的技巧啊

    */

    题目大意:

    有n的物品(n<=30),平均(两个人得到的物品差不能大于1)分给两个人,每个物品在每个人心目中的价值分别为(vi,wi)

    问两人心目中的价值差最小是多少。

    分析:

    直接暴搜目测会超时

    想到先搜索前一半,用数组a[0][i]保存第一个人在前半段取 i 个物品两个人的差的所有情况;

    再搜索后一半保存两个人的差的相反数,用相同的规则保存在a[1][]中。

    要想总差最小只需要

    a[0][i]-a[1][num-i] (num=n/2或 n/2+1)的绝对值最小即可..

    找这个最小值可以用二分查找优化

    然后就不会超时了

    ac代码:

    #include <iostream>
    #include <stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<string>
    #include<ctype.h>
    using namespace std;
    #define inf  500000000
    int a[2][32][70000];
    int nn[2][32];
    int v[32],w[32];
    int n;
    void dfs(int now,int e,int num,int ans,int flag)
    {
        if(now>e)
        {
            a[flag][num][nn[flag][num]++]=ans;
            return;
        }
        int p=flag?(-1):1;
        dfs(now+1,e,num,ans-p*w[now],flag);
        dfs(now+1,e,num+1,ans+p*v[now],flag);
    }
    void ini()
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%d",v+i);
        }
        for(int i=0;i<n;i++)
        {
            scanf("%d",w+i);
        }
    }
    int fun(int val,int pos)
    {
        int res=inf;
        int num=nn[1][pos];
        if(val>a[1][pos][num-1])
        {
            return abs(val-a[1][pos][num-1]);
        }
        int k=upper_bound(a[1][pos],a[1][pos]+num,val)-a[1][pos];
        res=min(res,abs(val-a[1][pos][k]));
        if(k)
        {
            res=min(res,abs(val-a[1][pos][k-1]));
        }
        return res;
    }
    void solve()
    {
        int ans=inf;
        memset(nn,0,sizeof(nn));
        dfs(0,n/2-1,0,0,0);
        dfs(n/2,n-1,0,0,1);
        for(int i=0;i<2;i++)
        {
            for(int j=0;j<16;j++)
            {
                sort(a[i][j],a[i][j]+nn[i][j]);
            }
        }
        for(int i=0;i<=n/2;i++)
        {
            for(int j=0;j<nn[0][i];j++)
            {
                int x=a[0][i][j];
                int k=n/2-i;
                ans=min(ans,fun(x,k));
                if(n%2)
                {
                    k=n/2+1-i;
                    ans=min(ans,fun(x,k));
                }
            }
        }
        printf("%d
    ",ans);
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
            freopen("in.txt","r",stdin);
        #endif
        int t;
        scanf("%d",&t);
        while(t--)
        {
            ini();
            solve();
        }
        return 0;
    }
  • 相关阅读:
    uva 1362(区间dp+计数)
    uva 11174(排列组合+搜索)
    简单递推系列 uva习题
    基本计数方法系列 uva习题
    Codeforces Round #209 (Div. 2) Problem A Table(找规律)
    CodeChef November Challenge 2013 解题报告
    2012 chengdu现场赛 Browsing History HDU4464(简单字符串)
    CodeChef TechFest 2013 Cool Numbers(搜索)
    CodeChef Inscription 2013 Wonderland jewellery(简单题)
    页面滚动marquee标签
  • 原文地址:https://www.cnblogs.com/oneshot/p/4102449.html
Copyright © 2011-2022 走看看