您的位置:首页 > 编程语言 > Go语言

HDU 4341 Gold miner (分组背包问题)

2013-04-10 21:01 405 查看
Gold miner

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 1124    Accepted Submission(s): 458

Problem Description Homelesser likes playing Gold miners in class. He has to pay much attention to the teacher to avoid being noticed. So he always lose the game. After losing many times, he wants your help.

To make it easy, the gold becomes a point (with the area of 0). You are given each gold's position, the time spent to get this gold, and the value of this gold. Maybe some pieces of gold are co-line, you can only get these pieces in order. You can assume it can turn to any direction immediately. Please help Homelesser get the maximum value.  

Input

There are multiple cases. In each case, the first line contains two integers N (the number of pieces of gold), T (the total time). (0<N≤200, 0≤T≤40000) In each of the next N lines, there four integers x, y (the position of the gold), t (the time to get this gold), v (the value of this gold). (0≤|x|≤200, 0<y≤200,0<t≤200, 0≤v≤200)  

Output

Print the case number and the maximum value for each test case.  

Sample Input

3 10

1 1 1 1

2 2 2 2

1 3 15 9

3 10

1 1 13 1

2 2 2 2

1 3 4 7  

Sample Output

Case 1: 3

Case 2: 7  

思路:题目由于对于共线的点,必须按顺序去拿,可以按点的x做升序排序,然后把斜率相同的点分到同一个组。对于同组的点,第一个点的价值为v1,时间为t1,第二个点的价值为v1+v2,时间为t1+t2,接下来是v1+v2+v3,t1+t2+t3...以此类推,这样就能保证同组里的每一个物品是互斥的,并且是按顺序去拿的。分组分好以后,就是直接按分组背包的做法做了。




View Code

1 #include <iostream>
2 #include <cstdio>
3 #include <cstring>
4 #include <cmath>
5 #include <algorithm>
6 #define MAX 40005
7 #define SIZE 205
8
9 using namespace std;
10
11 struct Gold
12 {
13     int x,y,t,v;
14 };
15
16 int line[SIZE][SIZE],num[SIZE]; //line存储分组情况,其中line[1][1]代表的是第一组第一个物品,num存的是该组里物品的件数
17 bool used[SIZE]; //判断该物品是否已经被纳入一个物品组中
18 Gold gold[SIZE];
19 int dp[MAX];
20 int N,T;
21
22 bool cmp(Gold a,Gold b) //升序
23 {
24     return abs(a.x) < abs(b.x);
25 }
26
27 void init()
28 {
29     memset(dp,0,sizeof(dp));
30     memset(line,0,sizeof(line));
31     memset(num,0,sizeof(num));
32     memset(used,0,sizeof(used));
33 }
34
35 int main()
36 {
37     int Case = 1;
38     while(~scanf("%d%d",&N,&T))
39     {
40         for(int i=1; i<=N; i++)
41             scanf("%d %d %d %d",&gold[i].x, &gold[i].y, &gold[i].t, &gold[i].v);
42         sort(gold+1, gold+1+N, cmp);
43         init();
44         int index = 1;
45         for(int i=1; i<=N; i++) //分组
46         {
47             if(used[i])continue;
48             used[i] = true;
49             line[index][++num[index]] = i; //存储该组的第一件物品
50             for(int j=i+1; j<=N; j++)
51             {
52                 if(!used[j] && gold[i].x*gold[j].y == gold[i].y*gold[j].x)
53                 {
54                     line[index][++num[index]] = j; //把斜率相同的放到同个组
55                     used[j] = true;
56                 }
57             }
58             index ++;
59         }
60         index --;
61         for(int i=1; i<=index; i++) //更新组成员的价值和时间
62         {
63             for(int j=2; j<=num[i]; j++)
64             {
65                 gold[line[i][j]].t += gold[line[i][j-1]].t;
66                 gold[line[i][j]].v += gold[line[i][j-1]].v;
67             }
68         }
69         for(int i=1; i<=index; i++) //分组背包
70         {
71             for(int j=T; j>=0; j--)
72             {
73                 for(int k=1; k<=num[i]; k++)
74                     if(j-gold[line[i][k]].t>=0)
75                         dp[j] = max(dp[j],dp[j-gold[line[i][k]].t]+gold[line[i][k]].v);
76             }
77         }
78         printf("Case %d: %d\n",Case++,dp[T]);
79     }
80     return 0;
81 }


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: