UVA 10273 Eat or Not to Eat?

这个题目一直以为是要用图论知识来做,可是一点建图的思绪都没有,后来知道暴力便可破之。由于牛的产奶周期最大为10,1.2.3.....10的最小公倍数是MT = 2520,所以把MT作为最大的周期,然后枚举这个周期内的每一天,看产奶量最小的牛是否唯一,然后杀掉是唯一的最少产奶的那头牛,知道遇到一个周期内没有牛被杀掉。这样就到达了一个稳定的最终状态,统计剩下的牛,和杀掉最后一头牛用去的时间。注意一头牛都不杀的情况应该输出天数为0.

不过这题还有更加标准的做法,刘汝佳黑书中提到,将周期相同的奶牛产奶情况用一个堆来维护,每次用一个最小的代表去和其他周期的奶牛比较。删除操作效率比较高。

代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <climits>
 4 #include <cstring>
 5 #include <cstdlib>
 6 #include <cmath>
 7 #include <vector>
 8 #include <queue>
 9 #include <algorithm>
10 #define esp 1e-6
11 #define pb push_back
12 #define in  freopen("in.txt", "r", stdin);
13 #define out freopen("out.txt", "w", stdout);
14 #define print(a) printf("%d
",(a));
15 #define bug puts("********))))))");
16 #define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++)
17 #define inf 0x0f0f0f0f
18 using namespace std;
19 typedef long long  LL;
20 typedef vector<int> VI;
21 typedef vector<int>:: iterator IT;
22 typedef pair<int, int> pii;
23 #define N 2000
24 #define M 30
25 #define MT 2520
26 int vis[N], a[N][M], T[N], num[N];
27 int n;
28 int main(void)
29 {
30     int t;
31     scanf("%d", &t);
32     while(t--)
33     {
34         memset(vis, 0, sizeof(vis));
35         for(int i = scanf("%d", &n) - 1 ; i < n; i++)
36         {
37             for(int j = scanf("%d", T + i) - 1; j < T[i]; j++)
38                 scanf("%d", &a[i][j]);
39         }
40         int nT = 0, nNum = n, nDay = 0, last, temp, k;
41         while(1)
42         {
43             int Min,j;
44             temp = 0;
45             for(int i = 0; i < MT; i++)
46             {
47                 memset(num, 0, sizeof(num));
48                 for(j = 0, k = -1, Min = inf; j < n; j++)
49                     if(!vis[j])
50                     {
51                         if(Min == a[j][i % T[j]])
52                         {
53                             num[k]++;
54                         }
55                         else if(Min > a[j][i % T[j]])
56                         {
57                             Min = a[j][i % T[j]];
58                             k = j;
59                             num[j]++;
60                         }
61                     }
62                 if(k >= 0 && num[k] == 1)
63                 {
64                     temp++;
65                     vis[k] = 1;
66                     nNum--;
67                     last = i;
68                 }
69             }
70             if(temp)
71             {
72                 if(nT)
73                     nDay += MT;
74             }
75             else
76             {
77                 if(nT)
78                 nDay += last + 1;
79                 break;
80             }
81             nT++;
82         }
83         printf("%d %d
", nNum, nDay);
84     }
85     return 0;
86 }
原文地址:https://www.cnblogs.com/rootial/p/3317546.html