POJ 2454--Jersey Politics

来源:互联网 发布:淘宝如何加入全球购 编辑:程序博客网 时间:2024/05/16 16:02

题意:有N = 3*K个城市,每个城市有1000头牛,每个城市的牛支持A或B,请将这N个城市分为3个地区,每个地区含有K个城市,且要使至少两个地区A的支持率高。

题解:首先将输入进行处理,保存每个城市支持数的差值,然后进行排序,因为一定有解,所以在前2*K个城市当中一定可以找到两个都满足要求的划分,则剩余K个城市直接划分为一个地区。

典型的组合数DFS,为了达到从2*N个牛中选择K个牛组成一个地区,可以按照地区中的城市号递增地选择城市。

剪枝:

  1. 剩下的城市数已经不能组成一个地区。
  2. 设sum[i]为从第i个到第2*K个城市的总差值,已经达到的差值为sumDiff,因为已经城市支持率为逆序,则剩下的城市要划分到地区1能获得最大的差值只能从beginCity一直连续取K-cliqueSize个城市,即若sumDiff+sum[beginCity]-sum[K-cliqueSize+beginCity] <= 0则地区1肯定不能满足要求。
  3. 类似的,剩下的城市要划分到地区0能获得的最大差值就是把从N逆序连续取K-cliqueSize个的城市全部给地区1,即sum[1]-(sumDiff+sum[N-K+cliqueSize+1]) <= 0则地区0肯定不能满足要求。

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;struct node{    int num;    int index;    bool friend operator<(const node& a,const node& b)    {        return a.num > b.num;    }};class solve{private:    int K;    int N;    node* diffNum;    int* sumDiffNum;        //从第i个到N的总差值    char* clique;public:    solve(int k):K(k),N(3*k)    {        diffNum = new node[N+1];        sumDiffNum = new int[N+2];        clique = new char[N+1];        memset(clique,0,sizeof(char)*(N+1));        memset(sumDiffNum,0,sizeof(int)*(N+2));        processIn();        DFS(0,1,0);        printClique(0);    }    ~solve()    {        delete[] diffNum;        delete[] clique;        delete[] sumDiffNum;    }    int processIn();    int DFS(char cliqueSize,char beginCity,int sumDiff);    int printClique(char cliqueFlag);};int solve::printClique(char cliqueFlag){    if(cliqueFlag == 2)        return 0;    for(int i = 1;i <= N;i++)    {        if(clique[i] == cliqueFlag)        {            printf("%d\n",diffNum[i].index);        }    }    printClique(cliqueFlag+1);    return 0;}int solve::DFS(char cliqueSize,char beginCity,int sumDiff){    if(cliqueSize == K)    {        if(sumDiff <= 0||sumDiffNum[1]-sumDiff <= 0)            return 0;        return 1;    }    if(cliqueSize+N-beginCity+1 < K||       //剩下的城市数已不足以形成区       sumDiff+sumDiffNum[beginCity]-sumDiffNum[K-cliqueSize+beginCity] <= 0||       //剩下的地区1最大划分不满足要求       sumDiffNum[1]-(sumDiff+sumDiffNum[N-K+cliqueSize+1]) <= 0)       //剩下的地区0最大划分不满足要求        return 0;    for(int i = beginCity;i <= N;i++)    {        clique[i] = 1;        if(DFS(cliqueSize+1,i+1,sumDiff+diffNum[i].num))            return 1;        clique[i] = 0;    }    return 0;}int solve::processIn(){    int tmpNum;    for(int i = 1;i <= N;i++)    {        scanf("%d",&tmpNum);        diffNum[i].num = 2*tmpNum-1000;        diffNum[i].index = i;    }    sort(diffNum+1,diffNum+N+1);    for(int i = 2*K+1;i <= N;i++)        //直接输出的最小的K个城市    {        printf("%d\n",diffNum[i].index);    }    N -= K;    for(int i = N;i >= 1;i--)    {        sumDiffNum[i] += sumDiffNum[i+1]+diffNum[i].num;    }    return 0;}int main(){    int k;    while(~scanf("%d",&k))    {        solve poj_2454(k);    }    return 0;}


0 0