背包

源代码:

#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,k1,k2,i1[10001],i2[10001];
bool Rule(int t1,int t2)
{
    return t1>t2;
}
int main()
{
    int T;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d%d%d%d",&n,&m,&k1,&k2);
        for (int a=1;a<=k1;a++)
          scanf("%d",&i1[a]);
        for (int a=1;a<=k2;a++)
          scanf("%d",&i2[a]);
        sort(i1+1,i1+k1+1,Rule);
        sort(i2+1,i2+k2+1,Rule);
        for (int a=1;a<=k1;a++) //前缀和优化。
          i1[a]+=i1[a-1];
        for (int a=1;a<=k2;a++)
          i2[a]+=i2[a-1];
        int Room; //Room表示剩余的空间。
        if (n%3==2&&m%3==2&&(n==2||m==2)) //特判。
          Room=4;
        else
          Room=n*m%3;
        int Ans=0,Limit=min(k2,(n*m-Room)/3);
        for (int a=0;a<=Limit;a++) //贪心。
          Ans=max(Ans,i2[a]+i1[min(k1,(n*m-a*3)>>1)]);
        printf("%d\n",Ans);
    }
    return 0;
}

/*
    背包和物品可以看做二维平面,可以发现,除了特殊情况,1*3的物品最后可以只剩下小于3的空间。
    按价值排序,贪心即可。
    贪心还真是神奇,虽然不知道怎么证明的。
*/
posted @ 2016-10-29 11:46  前前前世。  阅读(162)  评论(0编辑  收藏  举报