hdu 4610 Cards

http://acm.hdu.edu.cn/showproblem.php?pid=4610

先求出每个数的得分情况,分数和得分状态,(1<<4)种状态

按分数从大到小排序 然后每种状态取一个数(如果有的话)

然后对 dp[i][j] 进行背包 dp[i][j] 表示的是选了i个数选的总状态为j情况下的最大值

然后根据每个 dp[i][j] 对数组剩余的数进行最优选择(在不破坏 最终状态 j 的情况下,尽量选单位分数高的)

最后求最大的情况

代码:

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<set>
#include<map>
#include<stack>
#include<vector>
#include<algorithm>
#include<queue>
#include<stdexcept>
#include<bitset>
#include<cassert>
#include<deque>
#include<numeric>

using namespace std;

typedef long long ll;
typedef unsigned int uint;
const double eps=1e-12;
const int INF=0x3f3f3f3f;
const ll MOD=1000000007;
const int H=1000005;
const int K=10005;
const int N=1005;
const int M=(1<<4);
struct node
{
    int a,b;
    int point,k;
}in[N];
bool prime(int x)
{
    if(x==1) return false;
    for(int i=2;i*i<=x;++i)
    if(x%i==0)
    return false;
    return true;
}
void get(node &x)
{
    int a=x.a;
    int num=0,sum=0;
    for(int i=1;i*i<=a;++i)
    if(a%i==0)
    {
        ++num;
        sum+=i;
        int j=a/i;
        if(i!=j)
        {++num;sum+=j;}
    }
    x.k=0;x.point=0;
    if(num==2)
    {x.point++;x.k|=1;}
    if(prime(num))
    {x.point++;x.k|=2;}
    if(prime(sum))
    {x.point++;x.k|=4;}
    int h=(int)(sqrt(1.0*a)+0.5);
    int h1=(int)(sqrt(1.0*h)+0.5);
    if(a==1||((num&1)==0&&((num>>1)&1)==0)||((num&1)==1&&h1*h1==h))
    {x.point++;x.k|=8;}
}
bool cmp(node x,node y)
{
    return x.point>y.point;
}
int main()
{
    //freopen("data.in","r",stdin);
    //freopen("1011.in","r",stdin);
    //freopen("1011.out","w",stdout);
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,k;
        scanf("%d %d",&n,&k);
        for(int i=0;i<n;++i)
        {
            scanf("%d %d",&in[i].a,&in[i].b);
            get(in[i]);
            if(i>0) printf(" ");
            printf("%d",in[i].point);
        }
        printf("
");
        int bit[4];
        for(int i=0;i<4;++i)
        scanf("%d",&bit[i]);
        sort(in,in+n,cmp);
        int dp[20][20];
        memset(dp,-1,sizeof(dp));
        dp[0][0]=0;
        bool had[20];
        memset(had,false,sizeof(had));
        for(int i=0;i<n;++i)
        if(had[in[i].k]==false)
        {
            had[in[i].k]=true;
            node &w=in[i];
            for(int i=M-1;i>=0;--i)
            for(int j=0;j<M;++j)
            if(dp[i][j]!=-1)
            {
                int l=i+1;
                int r=(j|w.k);
                dp[l][r]=max(dp[l][r],dp[i][j]+w.point);
            }
            w.b--;
        }
        int ans=-INF;
        for(int i=0;i<=16;++i)
        for(int j=0;j<16;++j)
        if(i<=k&&dp[i][j]!=-1)
        {
            int sum=dp[i][j];
            for(int l=0;l<4;++l)
            if((j&(1<<l))==0)
            sum+=bit[l];
            int w=k-i;
            for(int l=0;w>0&&l<n;++l)
            if((j|in[l].k)==j)
            {
                if(w>=in[l].b)
                {
                    w-=in[l].b;
                    sum+=(in[l].b*in[l].point);
                }else
                {
                    sum+=(w*in[l].point);
                    w=0;
                }
                if(w==0)
                break;
            }
            if(w==0)
            ans=max(ans,sum);
        }
        printf("%d
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/liulangye/p/3215159.html