Spinning Wheels

题意:有5个不透明圆盘,有各自的转速,每个圆盘上有W个缺口(1<=W<=5),给定缺口的位置和大小。将这5个圆盘串到一根棍子上,0度对齐,求多少秒后一束光能穿过这5个圆盘?


解题思路

  1. 简单模拟一下就行。对每个圆盘,根据转速确定多少秒后会回到初始状态,求这些时间的最小共倍数。只需要模拟到这个最小共倍数就行。为了简单,可以模拟到359秒,因为360秒后每个圆盘一定同时回到初始状态。
  2. 对每个模拟的状态,确定会不会有缺口有重叠,则光可以穿过,得到结果。
  3. 确定缺口重叠的方法:用一个数组wedges[i][j][k]保存这些缺口,代表第i个圆盘的第j个缺口的角度。wedges[i][j][0]为缺口起点,wedges[i][j][1]为缺口终点。因为每个圆盘有若干个缺口,所以这里有一个组合的问题。
  4. 对特定的缺口组合,用left保存缺口重叠的起点,right保存缺口重叠的终点。left初始化为第1个圆盘的缺口起点,right初始化为第1个圆盘的缺口终点。然后遍历后面的圆盘,计算重叠部分,更新left,right。如果计算到最后都有重叠,则此缺口组合满足光可以通过。如果计算过程中right > left则不能使光通过。计算过程中涉及到的角度转换问题详见代码。

代码

/*
ID: zc.rene1
LANG: C
PROG: spin
*/

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int speeds[5];
int wedge_num[5];
int wedges[5][5][2];

void Rotate(void)
{
    int i, j;
    for (i=0; i<5; i++)
    {
	for (j=0; j<wedge_num[i]; j++)
	{
	    wedges[i][j][0] = (wedges[i][j][0] + speeds[i]) % 360;
	    wedges[i][j][1] = (wedges[i][j][1] + speeds[i]) % 360;
	}
    }
}

int min(int a, int b)
{
    return a < b ? a : b;
}

int max(int a, int b)
{
    return a > b ? a : b;
}

int CanPass(int *index)
{
    int left = wedges[0][index[0]][0];
    int right = wedges[0][index[0]][1];
    int i, temp_left, temp_right;

    for (i=1; i<5; i++)
    {
	if (right < left)
	{
	    right += 360;
	}
	else
	{
	    left += 360;
	    right += 360;
	}
	temp_left = wedges[i][index[i]][0];
	temp_right = wedges[i][index[i]][1];
	if (temp_right < temp_left)
	{
	    temp_right += 360;
	}
	else
	{
	    temp_left += 360;
	    temp_right += 360;
	}
	left = max(left, temp_left);
	right = min(right, temp_right);

	if (right < left)
	{
	    return 0;
	}
	else
	{
	    left %= 360;
	    right %= 360;
	}
    }
    return 1;
}

int Check(void)
{
    int index[5];

    for (index[0]=0; index[0]<wedge_num[0]; index[0]++)
    {
	for (index[1]=0; index[1]<wedge_num[1]; index[1]++)
	{
	    for (index[2]=0; index[2]<wedge_num[2]; index[2]++)
	    {
		for (index[3]=0; index[3]<wedge_num[3]; index[3]++)
		{
		    for (index[4]=0; index[4]<wedge_num[4]; index[4]++)
		    {
			if (CanPass(index))
			{
			    return 1;
			}
		    }
		}
	    }
	}
    }
    return 0;
}

int main(void)
{
    FILE *fin, *fout;
    int i, j, angle, angle_size;

    fin = fopen("spin.in", "r");
    fout = fopen("spin.out", "w");

    memset(wedges, -1, 5*5*2*sizeof(int));

    for (i=0; i<5; i++)
    {
	fscanf(fin, "%d %d", &speeds[i], &wedge_num[i]);
	for (j=0; j<wedge_num[i]; j++)
	{
	    fscanf(fin, "%d %d", &angle, &angle_size);
	    wedges[i][j][0] = angle;
	    wedges[i][j][1] = (angle + angle_size) % 360;
	}
    }	

    for (i=0; i<360; i++)
    {
	if (Check())
	{
	    break;
	}
	Rotate();
    }

    if (i < 360)
    {
	fprintf(fout, "%d\n", i);
    }
    else
    {
	fprintf(fout, "none\n");
    }

    return 0;
}




































评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值