vijos1574 摇钱树

背景

2009NOIP余姚中学内部暑期集训
7月14号模拟赛第三题

描述

Cpg 正在游览一个梦中之城,在这个城市中有n棵摇钱树。。。这下,可让Cpg看傻了。。。可是Cpg只能在这个城市中呆K天,但是现在摇钱树已经成熟了,每天每棵都会掉下不同的金币。Cpg每天可以砍掉其中一颗,并获得其树上说有的金币(怎么会有这种好事。。。)。请你帮助Cpg算出他在这K天中最多能获得多少金币。

格式

输入格式

每个文件中有不超过10组测试数据。

每组测试数据:
第一行两个整数n,K (1<=K<=n<=1000)
第二行n个整数Mi (Mi <= 100000).表示Cpg刚看到这n棵树时每刻树上的金币数。

第三行n个整数 Bi.(Bi<=1000)表示每颗摇钱树,每天将会掉落的金币。

以n=K=0结束。

输出格式

对每组测试数据,输出仅一行,Cpg在K天中能获得的最大金币数。

样例1

样例输入1

3 3
10 20 30
4 5 6
4 3
20 30 40 50
2 7 6 5
0 0

样例输出1

47
104

限制

各个测试点1s

提示

样例1的解释:第一天摘第三个果子得到30,第二天摘第二个果子得到15,第三天摘第一个果子得到2,30+15+2=47

首先orz出题人。好题。

这道题我们对于发现他的最优子结构还是很容易的。

f[k][S]表示前k天用了S的子集的最优解,

转移f[k][S]=f[k-1][p];(p属于S).

我们观察一下它有没有贪心属性,很显然没有,你必须知道前面的装态。

但我们可以容易的发现如果取了其中几个,一定是减少快的在前面取。

我们不妨先排个序。

发现,我们不用需要S了,只要一个j表示前k天用了前j棵树。

不需要顺序了。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<cstdlib>
 7 #include<vector>
 8 using namespace std;
 9 typedef long long ll;
10 typedef long double ld;
11 typedef pair<int,int> pr;
12 const double pi=acos(-1);
13 #define rep(i,a,n) for(int i=a;i<=n;i++)
14 #define per(i,n,a) for(int i=n;i>=a;i--)
15 #define Rep(i,u) for(int i=head[u];i;i=Next[i])
16 #define clr(a) memset(a,0,sizeof(a))
17 #define pb push_back
18 #define mp make_pair
19 #define fi first
20 #define sc second
21 #define pq priority_queue
22 #define pqb priority_queue <int, vector<int>, less<int> >
23 #define pqs priority_queue <int, vector<int>, greater<int> >
24 #define vec vector
25 ld eps=1e-9;
26 ll pp=1000000007;
27 ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;}
28 ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;}
29 void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
30 //void add(int x,int y,int z){ v[++e]=y; next[e]=head[x]; head[x]=e; cost[e]=z; }
31 int dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1};
32 ll read(){ ll ans=0; char last=' ',ch=getchar();
33 while(ch<'0' || ch>'9')last=ch,ch=getchar();
34 while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
35 if(last=='-')ans=-ans; return ans;
36 }
37 #define N 1005
38 struct node{
39     int a,b;
40 }f[N];
41 bool cmp(node a,node b){
42     return a.b>b.b;
43 }
44 int dp[N][N];
45 int main(){
46     while (1){
47         int n=read(),k=read();
48         if (n==0 && k==0) break;
49         for (int i=1;i<=n;i++) f[i].a=read();
50         for (int i=1;i<=n;i++) f[i].b=read();
51         sort(f+1,f+n+1,cmp);
52         memset(dp,0,sizeof(dp));
53         for (int i=1;i<=k;i++){
54             for (int j=1;j<=n;j++)
55                 dp[i][j]=max(dp[i][j-1],dp[i-1][j-1]+f[j].a-(i-1)*f[j].b);
56         }
57         int ans=0;
58         for (int i=1;i<=k;i++) ans=max(ans,dp[i][n]); 
59         printf("%d
",ans);
60      }
61 } 
View Code
原文地址:https://www.cnblogs.com/SXia/p/6941280.html