zoukankan      html  css  js  c++  java
  • 【BZOJ3661】Hungry Rabbit 贪心

    【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?'
    ':' ');
    	return 0;
    }/*
    4 4 3 1
    1110
    1101
    1011
    0111
    */
  • 相关阅读:
    与众不同 windows phone (50)
    与众不同 windows phone (49)
    重新想象 Windows 8.1 Store Apps (93)
    重新想象 Windows 8.1 Store Apps 系列文章索引
    重新想象 Windows 8.1 Store Apps (92)
    重新想象 Windows 8.1 Store Apps (91)
    重新想象 Windows 8.1 Store Apps (90)
    重新想象 Windows 8.1 Store Apps (89)
    重新想象 Windows 8.1 Store Apps (88)
    重新想象 Windows 8.1 Store Apps (87)
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7515465.html
Copyright © 2011-2022 走看看