【二进制枚举小记】杀怪物

描述

为了庆祝自己的生日,小张推出一款游戏。游戏在一个20*20的方格上进行,上面有一些怪物,用#表示,其他是空格,用 . 表示。怪物有两点体力。体力为0时死亡。 你可以进行以下操作: (1)使一个横行上的怪物体力减一 (2)使一个竖行上的怪物体力减一 对每个横行或竖行只能操作一次,限定n次,问最多能杀死多少个怪物。

输入

第一行为整数n(1≦n≦40),表示操作的次数。 接下来是一个20*20的方格,#表示怪物,.表示空格。

输出

输出最多能杀死的怪物数量。

测试点

时限:4s,内存:128m

AC代码

#include<bits/stdc++.h>
using namespace std;
char ch[25][25];
int n,a[25][25],ans,b[25];
int main(){
	cin>>n;
	for(int i=0;i<20;i++){
		for(int j=0;j<20;j++){
			cin>>ch[i][j];
			if(ch[i][j]=='#') a[i][j]=1;
		}
	}
	for(int i=0;i<(1<<20);i++){ //先枚举在特定行的操作次数 
		memset(b,0,sizeof(b));
		int cnt=0;
		for(int j=0;j<20;j++){
			if(i&(1<<j)){//如果二进制枚举第j位为1,那就操作第j行 
				++cnt;
				//统计第j行的怪物数,存到数组b中 
				for(int k=0;k<20;k++){
					if(a[j][k]) ++b[k];
				}
			}
		}
		if(cnt>n) continue;//枚举行操作次数>总操作次数,是不合理的,提前结束 
		if(n-cnt>20) continue;//剩下的次数大于20次 ,也是不合理的,提前结束 
		sort(b,b+20);//对于b数组,做一个排序,选怪物最多的n-cnt列操作 
		int s=0;
		//统计本轮枚举杀死怪物的最大数 
		for(int j=1;j<=n-cnt;j++){
			s+=b[20-j];
		}
		ans=max(s,ans);//更新最优解 
	}
	cout<<ans;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值