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
    */
  • 相关阅读:
    MySQL之三---MySQL数据库的二进制安装、源码编译和基础入门操作
    yum仓库搭建、http源码编译和磁盘分区
    linux 磁盘管理三部曲——(3)mount挂载,/etc/fstab配置文件
    linux 磁盘管理三部曲——(2)管理分区,文件系统类型格式化
    linux 磁盘管理三部曲——(1)磁盘结构,认识分区
    ssh WARNING:REMOTE HOST IDENTIFICATION HAS CHANGED(警告:远程主机标识已更改)
    httpd源码编译安装
    001 直接throw new RuntimeException("xxx")的异常错误信息是谁打印的?
    77 注解(二)——反射机制读取注解
    76 注解(一)——常用注解、自定义注解、注解的参数
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7515465.html
Copyright © 2011-2022 走看看