首页 > 技术文章 > 采药

ShuraK 2017-11-17 19:44 原文

采药(jdoj1049)

    题目大意:不同于NOIP的采药,这道题的描述都是一样的,只是数据范围有毒。

    注释:总时间和药的种类全是100,000,每种药的时间和价值不大于10。

      想法:如果想NOIP那道题一样用01背包跑的话,时间复杂度是O(10^10),显然会T掉,所以,我们想拓展一下别的方法,显然,极其容易注意到每种药物的时间和价值实在是太小了,所以在处理的过程中必定会有很多药物是一模一样的,所以,想到——多重背包。但是单纯的多重背包的时间复杂度是不发生改变的,所以我们极其容易想到一种优化——二进制优化。二进制的原理是一串2的每次加上剩余的数,是一定可以凑出所有的数的,这就是二进制优化的原理。说到这儿,这题就切了......

    最后,附上丑陋的代码......

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 int a[100100];
 7 int aa[20][20];
 8 int x[100];
 9 int cnt;
10 void two(int k)//二进制优化
11 {
12     cnt=0;
13     if(k==1)
14     {
15         x[++cnt]=1;
16         return;
17     }
18     else if(k==0)
19     {
20         return;
21     }
22     else
23     {
24         k--;
25         x[++cnt]=1;
26         int now=1;
27         while(1)
28         {
29             if(k>now*2)
30             {
31                 k-=now*2;
32                 x[++cnt]=now*2;
33                 now*=2;
34             }
35             else
36             {
37                 x[++cnt]=k;
38                 return;
39             }
40         }
41     }
42 }
43 int main()
44 {
45     int n,m;
46     scanf("%d%d",&n,&m);
47     int time,val;
48     for(int i=1;i<=n;i++)
49     {
50         scanf("%d%d",&time,&val);
51         aa[time][val]++;
52     }
53     for(int i=1;i<=10;i++)
54     {
55         for(int j=1;j<=10;j++)
56         {
57             memset(x,0,sizeof(x));//important ! important !! important !!!
58             two(aa[i][j]);
59             for(int ii=1;ii<=cnt;ii++)
60             {
61                 for(int jj=m;jj>=i*x[ii];jj--)
62                 {
63                     a[jj]=max(a[jj],a[jj-i*x[ii]]+x[ii]*j);
64                 }
65             }
66         }
67     }
68     int minn=-1;
69     for(int i=m;i>=1;i--) minn=max(minn,a[i]);
70     printf("%d",minn);
71 }

 

    小结:错误

        1.清数组。

    转载请注明:http://www.cnblogs.com/ShuraK/p/7853217.html

 

推荐阅读