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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章