【JZOJ3949】【湖南省队集训2014】Hungry Rabbit(贪心or网络流)

Problem

  给出n(≤800)只兔子在m(≤800)天内是否会被抓,然后求出一种在m天内每天派出k(≤n)只兔子的方案,要求保证该方案每次出去的兔子都不会被吃且相邻两天派出兔子的差异数不超过L(≤k)。

Solution

  比赛时我觉得这题很奇怪,感觉可能是道贪心题,并且想了一下,但是思考方向有点问题;随后我又想到了网络流,但没想到怎么建图;于是最后就打了暴力。
  正解的话,其实贪心和网络流都可以。

网络流:40~100points

  首先,对于每一只兔子,我们都给它拆成m个点,分别表示m天中每一天的它。
  由于我们要求保证每次出去的兔子都不会被吃,那么若有一个点会被吃,我们当然不管它。
  那么我们就要保证相邻两天派出兔子的差异数不超过L了。这里的方法比较巧妙,自己想应该比较难想,那就是在相邻两天中设置两个转换点u1,u2。设这相邻的两天为p,q,且p+1=q,那么我们从第p天中的所有点向u1各连一条容量为1的边,从u1向u2连一条容量为L的边,从u2向第q天中的所有点各连一条容量为1的边。但是我们知道,如果有只兔子两天都不会被吃,那么我们让它两天都出来是不会增加差异数的,所以我们从第p天中的所有兔子向第q天中的它连一条容量为1的边。
  但是如果我们按上述所做,那么每一个代表兔子的点可能会经过超过2的流量。比如举个浅显的栗子:设有兔1和兔2,L为1,第一天两兔都出去了,但是我们从第一天的兔1向第二天的兔1流了1的流量,又从第一天的兔2向第二天的兔1流了1的流量,这样就会导致第二天的兔1被派出了两次。如何防止这种情况发生呢?
  其实比较简单,就是把每一天中的每一只兔子都拆成两个点,从前排的点向后排的点连一条容量为1的边,前排的点负责接收,后排的点负责排出。那么由于有了这条神奇的边的限制,每一天中的每一只兔子所对应的点就最多只会经过1的流量了。
  于是按照常规套路,新建源点和汇点,从源点向第一天的点各连一条容量为1的边,从第m天的点向汇点各连一条容量为1的边,跑一遍最大流,看看最大流是否不小于k,小于则无解。但如何求出一种方案呢?
  其实也很简单,你直接看一下哪些边被流过了,那么说明我们的方案会经过那条边。然后有可能我们的方案中的一天会出现超过k只兔子(毕竟我们可以某些经过转换点u1,u2,某些直接流向下一天的同一只兔子),那么我们随便选k只兔子即可,毕竟这样做差异数会只少不多。
  时间复杂度: O() O ( 玄 ) 友情提示:根据我们使用算法的不同,打网络流会得到不同的分数。由于本题中的图较为稠密,打dinic在JZOJ能有90points。100points,则可能是高标推进。

Code

  由于lyl试过了,但没过,所以我并没有打网络流。

贪心:100points

  首先,我在比赛时就已经想到了一种最优策略:即不断地派出能持续最多天数的兔子。但是由于我的思考方向有点问题(我想的是先算出每只兔子的各段持续天数,然后丢进堆里,不断取最长),我不假思索地否定了我的想法。
  但其实正解也差不多,只不过它是对于每一天都要选择从这天开始的、能持续最多天数的兔子。但是我们还得保证差异数≤L。
  于是我们可以设a[i][j]表示第i天、第j只兔子往后最多能持续的天数(若它在第i天就会被吃则为0),然后先将第一天的兔子按a从大到小排个序,选择前k个。对于每个第i天(i>1),我们将第i-1天选择的兔子的信息(a和编号)存储在p数组里,将其他未选的兔子的信息存储在q数组里,那么将p从小到大排序,将q从大到小排序,然后将这两个数组的前L个值交换,直到当前的p[j]≥q[j]。
  正确性显然。
  时间复杂度: O(nmlog2n) O ( n m l o g 2 n )

Code
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
#define N 810
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
int i,j,l,n,m,k,L,ans[N][N];
char ch,map[N][N];
bool bz[N];
struct rabbit
{
    int num,len;
}a[N][N],p[N],q[N];
inline bool operator<(const rabbit&a,const rabbit&b)
{
    return a.len<b.len;
}
inline bool operator>(const rabbit&a,const rabbit&b)
{
    return a.len>b.len;
}
inline bool cmp(rabbit a,rabbit b)
{
    return a>b;
}
inline void print()
{
    printf("-1");
    exit(0);
}
int main()
{
    scanf("%d%d%d%d",&n,&m,&k,&L);
    fo(i,1,n)
    {
        do
            ch=getchar();
        while(ch!='0'&&ch!='1');
        map[i][1]=ch;
        fo(j,2,m)map[i][j]=getchar();
    }
    fd(i,m,1)
        fo(j,1,n)
            a[i][j].num=j,a[i][j].len=map[j][i]=='1'?1+a[i+1][j].len:0;
    memcpy(p,a[1],sizeof p);
    sort(p+1,p+n+1,cmp);
    fo(i,1,k)
    {
        ans[1][i]=j=p[i].num;
        if(map[j][1]=='0')print();
    }
    fo(i,2,m)
    {
        memset(bz,1,sizeof bz);
        fo(j,1,k)p[j].len--,bz[p[j].num]=0;
        l=0;
        fo(j,1,n)
            if(bz[j])
                q[++l]=a[i][j];
        sort(p+1,p+k+1);
        sort(q+1,q+l+1,cmp);
        fo(j,1,min(L,l))
        {
            if(!(p[j]<q[j]))break;
            swap(p[j],q[j]);
        }
        fo(j,1,k)
        {
            if(!p[j].len)print();
            ans[i][j]=p[j].num;
        }
    }
    fo(i,1,m)
    {
        sort(ans[i]+1,ans[i]+k+1);
        fo(j,1,k)
        {
            l=ans[i][j];
            printf(j<k?"%d ":"%d\n",l);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这个错误通常是由于使用的协议或密码套件不适用导致的。根据引用\[1\]和引用\[2\]的解决方法,你可以尝试以下步骤来解决这个问题: 1. 检查你的代码中使用的协议和密码套件是否被禁用或不适用。你可以根据引用\[3\]中的方法,将使用的协议改为null,例如将"TLSv1"改为null。 2. 确保你的JDK版本是最新的,并且已经安装了最新的安全更新。有时候,旧版本的JDK可能会导致协议或密码套件不适用。 3. 如果你使用的是第三方库或框架,确保它们支持你所需的协议和密码套件。有时候,一些库可能会限制可用的协议和密码套件。 4. 如果以上方法都没有解决问题,你可以尝试使用其他的HTTP客户端库,例如OkHttp或Apache HttpClient,看看是否能够解决该问题。 总之,这个错误通常是由于协议或密码套件不适用导致的。通过检查代码中使用的协议和密码套件,并确保JDK版本是最新的,你应该能够解决这个问题。 #### 引用[.reference_title] - *1* *3* [javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher su 解决...](https://blog.csdn.net/weixin_44629395/article/details/127123945)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [No appropriate protocol (protocol is disabled or cipher suites are inappropriate)](https://blog.csdn.net/stay_hungry520/article/details/124479583)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值