ZOJ 3211 Dream City

贪心,$dp$。

假设我们知道要选择哪些物品,那么这些物品应该按什么顺序选择呢?

物品$A(a1,b1)$,物品$B(a2,b3)$。

假设物品$A$在第$x$天被选择,物品$B$在第$y$天被选择。$x<y$。那么收益为:$P1=a1+(x-1)*b1+a2+(y-1)*b2$。

假设物品$A$在第$y$天被选择,物品$B$在第$x$天被选择。$x<y$。那么收益为:$P2=a1+(y-1)*b1+a2+(x-1)*b2$。

$P1>P2$的条件为:$(x-1)*b1+(y-1)*b2>(y-1)*b1+(x-1)*b2$,即$(y-x)*(b2-b1)>0$,即$b2>b1$。

也就是说,假设我们知道要选择哪些物品,那么这些物品按$b$从小到大取获得的收益最大。

因此,我们可以降物品按照$b$从小到大排序,然后去决策应该选择哪些物品,$dp$即可。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<ctime>
#include<iostream>
using namespace std;
typedef long long LL;
const double pi=acos(-1.0);
void File()
{
    freopen("D:\\in.txt","r",stdin);
    freopen("D:\\out.txt","w",stdout);
}
template <class T>
inline void read(T &x)
{
    char c = getchar();
    x = 0;
    while(!isdigit(c)) c = getchar();
    while(isdigit(c))
    {
        x = x * 10 + c - '0';
        c = getchar();
    }
}

int T,n,m;


struct X
{
    int a,b;
}s[300];

bool cmp(X a, X b)
{
    return a.b<b.b;
}

int dp[300][300];

int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%d",&s[i].a);
        for(int i=1;i<=n;i++) scanf("%d",&s[i].b);

        sort(s+1,s+1+n,cmp);

        memset(dp,0,sizeof dp);

        dp[1][1]=s[1].a;
        for(int i=2;i<=n;i++) dp[i][1]=max(dp[i-1][1],s[i].a);

        for(int j=2;j<=m;j++)
        {
            for(int i=j;i<=n;i++)
            {
                dp[i][j]=max(dp[i-1][j],dp[i-1][j-1]+s[i].a+(j-1)*s[i].b);
            }
        }

        printf("%d\n",dp[n][m]);

    }
    return 0;
}

 

posted @ 2017-02-15 15:39  Fighting_Heart  阅读(153)  评论(0编辑  收藏  举报