现在的位置: 首页 > 综合 > 正文

poj 2454 Jersey Politics dfs

2014年10月09日 ⁄ 综合 ⁄ 共 1152字 ⁄ 字号 评论关闭

这个题目第一步还是比较明显的,先把最小的n个值去掉,剩下的问题就是能不能把数据分成两半,使得每一半和都大于n*500,这个刚开始考虑了下dp的做法,但是复杂度不满足要求。

那么能想到的就是搜索了,实际上这个搜索的上限还是比较高的,就只能依靠良好的剪枝试试了,两个情况,剩下的值全部选最大还小于要求,剩下的值全部选最小另一半还小于要求。0ms ac

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=200;
struct D
{
    int key,id;
    bool operator <(const D &xx)const
    {
        return key>xx.key;
    }
}data[maxn];

bool cmp(const D &p,const D &q)
{
    return p.key<q.key;
}

int sum[maxn],n;
bool use[maxn],flag;
void dfs(int t,int ret,int ans)
{
//    printf("%d %d\n",ret,ans);
    if(flag) return ;
    if(ret==n)
    {
        if(ans>n*500&&sum[n+n]-ans>n*500)
        {
            for(int i=1;i<=n+n;i++)
            if(use[i])
            printf("%d\n",data[i].id);
            for(int i=1;i<=n+n;i++)
            if(!use[i])
            printf("%d\n",data[i].id);
            flag=true;
        }
        return ;
    }
    if(ans+sum[t]-sum[t-(n-ret)]<=n*500) return ;
    if(sum[n+n]-(ans+sum[n-ret])<=n*500) return ;
    for(int i=t;i>=n-ret;i--)
    {
        use[i]=1;
        dfs(i-1,ret+1,ans+data[i].key);
        use[i]=0;
    }
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n*3;i++)
    {
        scanf("%d",&data[i].key);
        data[i].id=i;
    }
    sort(data+1,data+1+n*3);
    sort(data+1,data+1+n+n,cmp);
    sum[0]=0;
    for(int i=1;i<=n+n;i++)
    sum[i]=sum[i-1]+data[i].key;
    flag=0;
    memset(use,0,sizeof(use));
    dfs(n+n,0,0);
    for(int i=n+n+1;i<=n*3;i++)
    printf("%d\n",data[i].id);
    return 0;
}

抱歉!评论已关闭.