zoukankan      html  css  js  c++  java
  • 【BZOJ4716】假摔 二分+暴力

    【BZOJ4716】假摔

    Description

    【题目背景】
    小Q最近喜欢上了一款游戏,名为《舰队connection》,在游戏中,小Q指挥强大的舰队南征北战,从而成为了一名dalao。在游戏关卡的攻略中,可能由于作战过程中某艘船受到严重损伤,为避免沉没而被迫进行返航,这种情况大家称为这艘船“假摔”。小Q最喜欢使用的一艘战舰代号为P01,但是最近这艘船总是用各种不同的姿势假摔,于是小Q打算研究一下原因。
    【题意描述】
    P01的装甲可以近似看作一个n*m的矩阵,每个位置上的数字代表这个位置装甲的强度。当受到炮击时,防御力为被炮击的部分的所有位置强度之和。最近小Q发现,敌方有一种船只被称为ENE,它可以发射不同形状的炮弹,以达到攻击装甲最薄弱处的目的。P01已经被连续k次用不同方式打成了严重损伤(假摔),于是小Q打算分析一下ENE的攻击力。为了简单起见,我们作如下假设:
    1、ENE的炮弹形状无论如何变化,火力值都为一个定值(整数,未知)
    2、ENE的炮弹形状只能是长方形(ENE:呵呵),且由于口径的限制,炮弹不能太小(具体来说,对于每一发炮弹长xi宽yi,有xmin<=xi<=n,ymin<=yi<=m)
    3、当ENE的炮击命中P01的某处装甲时,被命中部分的强度之和为P01的防御力,此时,ENE的火力必须严格大于P01的防御力,才能将其击穿并造成严重损伤(假摔)。
    然而,小Q并没有得到详细的中弹数据,只知道P01用k种不同的方式假摔过。两种假摔方式不同,当且仅当受到炮击的位置不完全相同。因此,不同形状的炮弹击穿护甲时必定可以造成不同的假摔方式,而相同形状的炮弹在不同的位置击穿护甲也能造成不同的假摔方式。现在,小Q想估计ENE的火力最低是多少。于是,这个任务被交给了你。
    举例而言,假设P01的护甲为3*4:
    0 1 3 7
    1 1 5 5
    7 6 9 6
    如果ENE的口径至少为2*2,那么直接使用2*2的炮弹攻击左上角2*2的装甲时,只要火力>=4即可造成一种假摔。如果想造成k=3种不同的假摔方式,至少要拥有12的火力,此时可以造成如下三种假摔方式:
    1、2*2炮弹,攻击有数字的部分,装甲值为3
    0 1 - -
    1 1 - -
    - - - -
    2、2*2炮弹,攻击有数字的部分,装甲值为10
    - 1 3 -
    - 1 5 -
    - - - -
    3、2*3炮弹,攻击有数字的部分,装甲值为11
    0 1 3 -
    1 1 5 -
    - - - -
    可以证明,火力小于12时,无法造成3种不同的假摔方式,所以ENE的火力至少应为12。

    Input

    第一行,五个数n, m, xmin, ymin, k,空格分隔。
    接下来n行,每行m个数,空格分隔,表示P01的装甲。
    1<=n,m<=1000,1<=xmin<=n, 1<=ymin<=m, 1<=k<=250000,装甲值为不超过2000的非负整数。
    保证火力为无穷大的ENE可以造成k种不同的假摔方式。

    Output

    仅一行,一个数,表示ENE的火力最低值。

    Sample Input

    3 4 2 2 3
    0 1 3 7
    1 1 5 5
    7 6 9 6

    Sample Output

    12

    题解:一开始瞎写了写没写出来,看网上的题解神的不行,后来发现网上的题解都想多了!!!直接二分+暴力就行!

    先二分答案,然后枚举右下角的点,然后不断移动左上角的点,直到不能再移动为止。因为每次移动要么会break要么会使方案数+1,并且k<250000,所以总复杂度是有保证的!是O(log(ans)*(n*m+k))!

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    int n,m,xn,yn,K;
    int s[1010][1010];
    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;
    }
    inline int calc(int a,int b,int c,int d)
    {
    	return s[c][d]-s[a][d]-s[c][b]+s[a][b];
    }
    bool check(int x)
    {
    	register int i,j,a,b;
    	int ret=K;
    	for(i=xn;i<=n;i++)	for(j=yn;j<=m;j++)
    	{
    		for(a=i-xn;a>=0&&calc(a,j-yn,i,j)<x;a--)	for(b=j-yn;b>=0&&calc(a,b,i,j)<x;b--)
    		{
    			ret--;
    			if(!ret)	return 1;
    		}
    	}
    	return 0;
    }
    int main()
    {
    	n=rd(),m=rd(),xn=rd(),yn=rd(),K=rd();
    	int i,j;
    	for(i=1;i<=n;i++)	for(j=1;j<=m;j++)	s[i][j]=s[i-1][j]-s[i-1][j-1]+s[i][j-1]+rd();
    	int l=0,r=s[n][m]+1,mid;
    	while(l<r)
    	{
    		mid=(l+r)>>1;
    		if(check(mid))	r=mid;
    		else	l=mid+1;
    	}
    	printf("%d",r);
    	return 0;
    }
  • 相关阅读:
    详述@Responsebody和HTTP异步请求的关系
    利用synchronized解析死锁的一种形成方式
    初识Spring JdbcTemplate
    初识SpringIOC
    JasperReport框架使用教程(附带常见空白页问题说明)
    LeetCode~1033.移动石子直到连续
    LeetCode~941.有效的山脉数组
    LeetCode~344. 反转字符串
    Job for network.service failed because the control process exited with error code问题
    LeetCode~报数(简单)
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7629408.html
Copyright © 2011-2022 走看看