[51nod1614]刷题计划

  大赛将至,摆在你面前的是n道题目,第 i(1  i  n) 道题目能提升 ai 点智力值,代码量为 bi KB,无聊值为 ci ,求至少提升m点智力值的情况下,所做题目代码量之和*无聊值之和最小为多少。

 Input
  第一行两个整数n,m(0<n<=400)
  接下来n行每行三个整数,ai,bi,ci(0<bi,ci<=1000,0<ai<=800)。
  0<m<=Σai<=800
 Output
  一个数,至少提升m点智力值的情况下,所做题目代码量之和*无聊值之和的最小值。

 

 

  思路和求最小乘积生成树一样。。。不同的就是具体计算的时候是01背包而不是求mst。。。

  大概就是将一个方案的b值之和看成X坐标,c值之和看成Y坐标。那么答案的方案肯定就在所有点组成的凸包的左下部分上。

  直接丢题解网址了...http://www.51nod.com/onlineJudge/problemSolution.html#!problemId=1614

 

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<queue>
 6 #include<cmath>
 7 #include<cstdlib>
 8 #define ll long long
 9 #define ull unsigned long long
10 #define ui unsigned int
11 #define d double
12 #define ld long double
13 const int maxn=808;
14 
15 struct zs{int x,y;ll v;}f[maxn],a[maxn];
16 ll ANS,inf=1ll<<60;int SMA;
17 int A[maxn];
18 int i,j,k,n,m;
19 
20 int ra,fh;char rx;
21 inline int read(){
22     rx=getchar(),ra=0,fh=1;
23     while(rx<'0'&&rx!='-')rx=getchar();
24     if(rx=='-')fh=-1,rx=getchar();
25     while(rx>='0')ra=ra*10+rx-48,rx=getchar();return ra*fh;
26 }
27 
28 //bool operator <(zs a,zs b){return a.v<b.v;}
29 zs operator +(zs a,zs b){return (zs){a.x+b.x,a.y+b.y,a.v+b.v};}
30 zs operator -(zs a,zs b){return (zs){a.x-b.x,a.y-b.y,a.v-b.v};}
31 inline int cross(zs a,zs b){return a.x*b.y-a.y*b.x;}
32 
33 inline void upd(zs &a,zs &b,zs &c){if(b.v+c.v<a.v)a=b+c;}
34 inline zs get(){
35     register int i,j,k;zs ans=(zs){0,0,inf};
36     for(i=1;i<=SMA;i++)f[i].v=inf;
37     for(i=1;i<=n;i++)
38         for(j=SMA,k=j-A[i];j>=A[i];j--,k--)upd(f[j],f[k],a[i]);
39     for(j=m;j<=SMA;j++){
40         if(f[j].v<ans.v)ans=f[j];
41         if(1ll*f[j].x*f[j].y<ANS)ANS=1ll*f[j].x*f[j].y;
42     }
43     return ans;
44 }
45 inline void run(zs A,zs B){
46     for(register int i=1;i<=n;i++)a[i].v=a[i].x*(A.y-B.y)+a[i].y*(B.x-A.x);
47     zs C=get();
48     if(cross(B-A,C-A)>=0)return;
49     run(A,C),run(C,B);
50 }
51 
52 int main(){
53     n=read(),m=read();
54     for(i=1;i<=n;i++)A[i]=read(),a[i].x=read(),a[i].y=read(),SMA+=A[i];
55     
56     ANS=inf;
57     for(i=1;i<=n;i++)a[i].v=a[i].x;zs A=get();
58     for(i=1;i<=n;i++)a[i].v=a[i].y;zs B=get();//printf("sty:%d (%d,%d)   stx:%d (%d,%d)\n",A.v,A.x,A.y,B.v,B.x,B.y);
59     //printf("ANS:%lld\n",ANS);
60     run(A,B);
61     printf("%lld\n",ANS);
62 }
View Code

 

posted @ 2016-10-11 21:23  czllgzmzl  阅读(417)  评论(0编辑  收藏  举报