uva 10273 Eat or not to Eat?

怎么个图论法??这题一读完题一直没有思路,不知道和图论有什么关系,倒是一开始就想到了暴力,但是见数据的规模,怕暴力会超时所以就没写一直歇了两天,没思路去找解题保报告,看了几下,都是暴力求解(和自己当初想的一样都是求lcm作为周期来计数),所以就写了一个暴力,一次成型没有debug过了sample直接丢上uva去,AC了,不过时间也比较糟糕1.100s左右。

 

#include <cstdio>
#include <cstring>
#define N 1010
#define M 15
bool killed[N];
int c[N];
int a[N][M];
int n;

int kill(int day)  //在day这天杀牛
{
    int min=260,cc=0,k,val;  //牛的最高产奶量为250
    for(int i=1; i<=n; i++) if(!killed[i])
    {
        val=a[i][ day%c[i] ];
        if(val==min) cc++;
        else if(val<min)
        { min=val,k=i; cc=1;}
    }
    if(cc==1) return k;
    else     return 0;

}
int gcd(int x , int y)  //得到两个数的最大公约数
{
    return y==0 ? x : gcd(y,x%y); 
}
int lcm(int x ,int y)  //得到两个数x,y的最小公倍数
{
    int tmp;
    if(x<y) { tmp=x; x=y; y=tmp; }
    int m=gcd(x,y);  //先得到两个数的最大公约数
    return x/m*y;
}
int get_lcm()
{
    int m=1;  //保存最后的最小公倍数

    for(int i=1; i<=n; i++) if(!killed[i])
        m=lcm(m,c[i]); 
    //用当前这只牛的周期和之前已经算出来的最小公倍数在算一次最小公倍数
    return m;
}
int main()
{
    int T,start,end,ccount,lastday;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&c[i]);
            for(int j=1; j<c[i]; j++)
                scanf("%d",&a[i][j]);
            scanf("%d",&a[i][0]);
        }
        memset(killed,0,sizeof(killed));
        ccount=0; start=1; lastday=0;
        while(1)
        {
            int OK=0;
            int L=get_lcm();//在剩余的牛中计算最小公倍数
            end=start+L-1;
            for(int i=start; i<=end; i++)  //枚举整个周期
            {
                int k=kill(i);  //杀牛,不能杀牛返回0,能杀牛则返回牛的编号
                if(k)
                {
                    killed[k]=1;  //标记
                    ccount++;     //计数
                    lastday=i;    //更新最后一天
                    OK=1;         //标记有杀牛
                }
            }
            start=end+1;  //准备下一个周期
            if(!OK || ccount>=n)  //在这一个周期没有杀牛或者牛全部杀光了
                break;
        }
        printf("%d %d\n",n-ccount,lastday);
    }
    return 0;
}    

 

后来发现这道题在黑书中有讲解(黑书的91页)。其原理是一个堆,这个堆有10个元素(10的意思是,题目中说明周期最大为10,每一个周期选一个代表元素出来并且用这10个元素进行建堆,并在操作中时刻维护这个堆),合并相同周期的奶牛并在周期内的每一天中选一个产奶量最小的来作为代表并且在操作过程中要不断修改这个代表。

这题说到底不算是暴力题也不算图论,算数据结构,而且zoj 1236 也是这道题,用这个暴力代码是不能AC的,会TLE,所以正解应该是用黑书所说的方法,找天把那个代码给写出来才行

posted @ 2012-12-18 19:46  Titanium  阅读(510)  评论(0编辑  收藏  举报