CodeForces - 1368F Lamps on a Circle(交互+贪心)

题目链接:点击查看

题目大意:给出一个环状的灯泡,标号为 1 ~ n ,初始时全部为熄灭状态,现在两个人开始玩游戏,第一个人可以选择继续游戏,也可以选择结束游戏,继续游戏的话首先选择一个正整数 k ,然后点亮 k 个熄灭的灯泡,第二个人可以选择连续的 k 个灯泡将其全部熄灭,如此往复,设 R( n ) 是 n 个灯泡的情况下,经过两人的数轮操作后可以亮着的最大灯泡数,第一个人可以在第二个人操作完后,亮着的灯泡不小于 R( n ) 时结束游戏

题目分析:一道需要制定贪心策略的题目,首先需要求出 R( n ) 为多少,首先假设当前亮着的灯泡数为 x ,第一个人选择的数字为 k ,这样下一轮第一个人经过操作后,亮着的灯泡数变为了 x + k ,因为第二个人可以选择 k 个连续的灯泡熄灭,如果本轮操作可以提供贡献的话,必须保证这 x + k 中最长的连续的亮着的灯泡是小于等于 k - 1 个的,这样第二个人熄灭连续的 k 个灯泡后,本轮的贡献仍然是 x + 1 ,我们需要求出这个 x 

因为一共 x + k 个亮着的灯泡,极限情况就是每 k - 1 个亮着的灯泡分成一组,又因为最长的连续的灯泡个数必须小于等于 k - 1 ,所以每两段之间需要有一个熄灭的灯泡隔开,画个图就是这样的:

浅蓝色表示的是环状的灯泡分布,深蓝色的是连续的 k - 1 个亮着的灯泡,红色的是熄灭的灯泡

这样显然熄灭的灯泡个数为 \left \lceil \frac{x+k}{k-1} \right \rceil,亮着的灯泡个数为 x + k ,总灯泡个数为 n ,所以列出不等式:\left \lceil \frac{x+k}{k-1} \right \rceil + x + k <= n

解得 x<=n-\left \lceil \frac{n}{k} \right \rceil-k,因为我们这个 x 的含义是,最后一次放之前亮着的灯的个数,所以在最后一次操作时,又放置了 k 个灯泡,对手拿走了 k - 1 个灯泡,此时达到 R( n ) 的局面,换句话说,其实 x<=n-\left \lceil \frac{n}{k} \right \rceil-k + 1 才对

这样我们可以枚举 k 维护出最大的 R( n ) ,找到 k 后贪心就好了,就像上面那个图一样,为了方便处理,我们设起点从 0 开始,不能放置的位置都为 i % k == 0 ,其余位置贪心填满就好了

代码:
 

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
using namespace std;

typedef long long LL;

typedef unsigned long long ull;

const int inf=0x3f3f3f3f;

const int N=2e5+100;

set<int>s;

int main()
{
#ifndef ONLINE_JUDGE
//  freopen("input.txt","r",stdin);
//  freopen("output.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);
	int n;
	scanf("%d",&n);
	int mmax=0,k=1;
	for(int i=1;i<=n;i++)
	{
		int temp=n-(n+i-1)/i-i+1;
		if(temp>mmax)
		{
			mmax=temp;
			k=i;
		}
	}
	for(int i=0;i<n;i++)
		if(i%k)
			s.insert(i);
	while(s.size()>=k)
	{
		printf("%d ",k);
		for(int i=0;i<k;i++)
		{
			printf(" %d",*s.begin()+1);
			s.erase(s.begin());
		}
		puts("");
		fflush(stdout);
		int pos;
		scanf("%d",&pos);
		pos--;
		for(int i=0;i<k;i++)
			if((pos+i)%n%k)
				s.insert((pos+i)%n);
	}
	puts("0");
	fflush(stdout);














    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_45458915/article/details/106862953