1. 程式人生 > >【BZOJ3661】Hungry Rabbit 貪心

【BZOJ3661】Hungry Rabbit 貪心

getc cpp swap hint inline 食物 blog 遭遇 turn

【BZOJ3661】Hungry Rabbit

Description

可怕的洪水在夏天不期而至,兔子王國遭遇了前所未有的饑荒,它們不得不去外面的森林裏尋找食物。
為了簡化起見,我們假設兔子王國中有n只兔子,編號為1n。在救濟糧到來之前的m天中,每天恰好有k只兔子需要去森林裏尋找糧食。森林裏居住著可怕的大灰狼,所幸兔子已經摸清了大灰狼捕食習慣,即狼們在每一天只會捕食特定編號的兔子。為了安全起見,兔子們需要保證每次出去覓食的k只兔子都不會被狼捕食。由於每天出去捕食的兔子都不盡相同,它們為每一天定義了一個生疏度pi,即第i天出來尋找食物,但是第i1天卻沒有出來覓食的兔子個數。規定第1天的生疏度為0.現在兔子們希望在保證安全的前提下,每天的生疏度不能超過L,請為兔子們構造一個合法的方案。

Input

第一行包括四個整數n,m,k和L.
接下來n行,每行一個長度為m的01串。其中第i行第j個字符若為0,則表示狼在第j天會捕食編號為i的兔子,為1則表示不捕食。

Output

m行,每行k個1-n之間互不相同的整數,代表這一天出去尋找食物的兔子編號。如果沒有合法方案,則輸出一行1即可。

Sample Input

5 4 3 1
1001
1101
1111
1110
0111

Sample Output

2 3 4
2 3 4
3 4 5
2 3 5

HINT

對於 100% 的測試數據,1 <= n;m <= 800; 1 <= k <= n; 1 <= l <= k

題解:一開始以為是個網絡流,結果正解居然是貪心。。。

我們先預處理出len[i][j]代表每一天的每只兔子最多能往後連續出去多少天,那麽每天我們一定是貪心的選擇len最大的出去。具體怎麽做呢?我們已知第i-1天出去的兔子集合是q,剩下的兔子的集合是p,那麽將p按len從大到小排序,將p按len從小到大排序,然後交換p和q的前L個(如果可以的話)。最後判斷一下是否可行即可。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
int n,m,now,K,L;
char str[810][810];
int f[810][810],len[810][810],r1[810],r2[810],vis[810],ans[810][810];
inline int rd()
{
	int ret=0,f=1;	char gc=getchar();
	while(gc<‘0‘||gc>‘9‘)	{if(gc==‘-‘)f=-f;	gc=getchar();}
	while(gc>=‘0‘&&gc<=‘9‘)	ret=ret*10+gc-‘0‘,gc=getchar();
	return ret*f;
}
bool cmp(int a,int b)
{
	return len[now][a]>len[now][b];
}
int main()
{
	scanf("%d%d%d%d",&n,&m,&K,&L);
	int i,j,*p=r1,*q=r2,tp;
	for(i=1;i<=n;i++)	scanf("%s",str[i]+1);
	for(j=m;j;j--)	for(i=1;i<=n;i++)	len[j][i]=(str[i][j]==‘0‘)?0:(len[j+1][i]+1);
	for(j=1;j<=m;j++)
	{
		now=j,tp=0;
		for(i=1;i<=n;i++)	if(len[j][i]&&!vis[i])	p[++tp]=i;
		sort(p+1,p+tp+1,cmp);
		if(j!=1)
		{
			sort(q+1,q+K+1,cmp);
			for(i=1;i<=L&&i<=tp;i++)	if(len[j][p[i]]>len[j][q[K-i+1]])	swap(p[i],q[K-i+1]);
			if(i!=K+1&&!len[j][q[K-i+1]])
			{
				printf("1");
				return 0;
			}
			memset(vis,0,sizeof(vis));
			swap(p,q);
		}
		else
		{
			if(tp<K)
			{
				printf("1");
				return 0;
			}
		}
		for(i=1;i<=K;i++)	vis[p[i]]=1,ans[j][i]=p[i];
		swap(p,q);
	}
	for(j=1;j<=m;j++)	for(i=1;i<=K;i++)	printf("%d%c",ans[j][i],i==K?‘\n‘:‘ ‘);
	return 0;
}/*
4 4 3 1
1110
1101
1011
0111
*/

【BZOJ3661】Hungry Rabbit 貪心