您的位置:首页 > 其它

Codeforces Round #288 (Div. 2) C. Anya and Ghosts

2015-02-05 11:23 253 查看
题意:有m个鬼,每个鬼到访1秒,要求鬼到访的这一秒有r根蜡烛是亮的。

每根蜡烛点燃需要1秒,可以亮t秒。问最少需要点燃多少根蜡烛。

如果不能满足所有鬼来时都有r根蜡烛是亮的,则输出-1。

若x秒时点燃蜡烛,则x+1到x+t秒该蜡烛照亮。

可以再任何整数时刻点燃蜡烛。

分析:

如果t<r则不可能有r根蜡烛同时照亮,否则一定可以满足条件。

在鬼来前点亮,越靠近鬼来的时刻越好。如果蜡烛不够,则从鬼来的时刻ghost[i]-1向前递推

t秒,看要补几根蜡烛。

这里要补的蜡烛一定是靠近鬼的,因为先点的蜡烛肯定已经燃尽了。

这样只要采用贪心策略加模拟就可以了。

由于鬼来的时间可能为1-300,蜡烛的数目为1-300,则可能在之前就把蜡烛点燃。为了方便处理,

把鬼来的时间推迟300s。这样点蜡烛的时间就可以在正整数范围0-600中确定了。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
#include<map>

using namespace std;

typedef long long ll;

int a[630],time[630];

int main()
{
    int m,t,r;
    while(~scanf("%d%d%d",&m,&t,&r))
    {
        memset(time,0,sizeof(time));
        for(int i=1;i<=m;i++)
        {
            scanf("%d",&a[i]);
            a[i] += 300;
        }
        if(r>t)
        {
            puts("-1");
            continue;
        }
        for(int i=1;i<=m;i++)
        {
            int check = 0;
            for(int j=a[i]-1;j>=a[i]-t;j--)
            {
                if(time[j]==1)
                    check++;
            }
            for(int j=a[i]-1;j>=(a[i]-(r-check));j--)
                time[j] = 1;
        }
        int ans = 0;
        for(int i=0;i<=600;i++)
            if(time[i]==1)
                ans++;
        cout<<ans<<endl;
    }
    return 0;
}


还看了2种很值得借鉴的代码实现。

其中一种思路差不多 来源于http://blog.csdn.net/logzhangrui/article/details/43274051

#include<stdio.h>
#include<string.h>
int main()
{
    int ghost[1010],time[1010];
    int m,t,r;
    while(scanf("%d%d%d",&m,&t,&r)!=EOF)
    {
        memset(ghost,0,sizeof(ghost));
        memset(time,0,sizeof(time));
        for(int i=1;i<=m;i++)
        {
            scanf("%d",&ghost[i]);
        }
        if(r>t)
        {
            printf("-1\n");
            return 0;
        }
        int sum=0;
        for(int i=1;i<=m;i++)
        {
            for(int j=ghost[i];r-time[ghost[i]]>0;j--)
            {
                sum++;
                for(int k=0;k<t;k++)
                    if(k+j>=0)
                    time[k+j]++;
            }
        }
        printf("%d\n",sum);
    }
    return 0;
}


另外一种是在codeforces上看到的。

他判断不可能的情况是 先把所有时刻0-600都放蜡烛。然后扫一遍尝试着减少

每个时刻的蜡烛,看是否仍然能满足条件。若能则灭掉蜡烛,否则点亮。一边

判断一边统计。

#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;

const int N = 2000;
int a
;
int n, r, t;
int b
;
const int T = 630;
int ans = T;

bool check()
{
	for (int i = 0; i < n; i++)
	{
		int cnt = 0;
		for (int j = a[i] - t; j < a[i]; j++)
			cnt += b[j];
		if (cnt < r)
			return false;
	}
	return true;
}

int main()
{
	scanf("%d%d%d", &n, &t, &r);
	for (int i = 0; i < n; i++)
	{
		scanf("%d", &a[i]);
		a[i] += 300;
	}
	for (int i = 0; i < T; i++)
		b[i] = 1;
	if (!check())
	{
		printf("-1\n");
		return 0;
	}
	for (int i = T - 1; i >= 0; i--)
	{
		b[i] = 0;
		if (!check())
			b[i] = 1;
		ans -= (1 - b[i]);
	}
	printf("%d\n", ans);

	return 0;
}


以上2种思路中各个时刻的蜡烛只有点亮和熄灭两种,而没有考虑有几根亮。

这种简化问题的转换值得思考(*^__^*) 嘻嘻……
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: