UVA 10273 Eat or Not to Eat?

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

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

代码:

 #include <iostream>
#include <cstdio>
#include <climits>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <algorithm>
#define esp 1e-6
#define pb push_back
#define in freopen("in.txt", "r", stdin);
#define out freopen("out.txt", "w", stdout);
#define print(a) printf("%d\n",(a));
#define bug puts("********))))))");
#define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++)
#define inf 0x0f0f0f0f
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef vector<int>:: iterator IT;
typedef pair<int, int> pii;
#define N 2000
#define M 30
#define MT 2520
int vis[N], a[N][M], T[N], num[N];
int n;
int main(void)
{
int t;
scanf("%d", &t);
while(t--)
{
memset(vis, , sizeof(vis));
for(int i = scanf("%d", &n) - ; i < n; i++)
{
for(int j = scanf("%d", T + i) - ; j < T[i]; j++)
scanf("%d", &a[i][j]);
}
int nT = , nNum = n, nDay = , last, temp, k;
while()
{
int Min,j;
temp = ;
for(int i = ; i < MT; i++)
{
memset(num, , sizeof(num));
for(j = , k = -, Min = inf; j < n; j++)
if(!vis[j])
{
if(Min == a[j][i % T[j]])
{
num[k]++;
}
else if(Min > a[j][i % T[j]])
{
Min = a[j][i % T[j]];
k = j;
num[j]++;
}
}
if(k >= && num[k] == )
{
temp++;
vis[k] = ;
nNum--;
last = i;
}
}
if(temp)
{
if(nT)
nDay += MT;
}
else
{
if(nT)
nDay += last + ;
break;
}
nT++;
}
printf("%d %d\n", nNum, nDay);
}
return ;
}
上一篇:自定义view获取宽高


下一篇:通过系统自带的内容提供器(ContentResolver)读取系统的通讯录,并设置点击事件