Winner Winner——状压dp(待定)

题目描述

The FZU Code Carnival is a programming competetion hosted by the ACM-ICPC Training Center of Fuzhou University. The activity mainly includes the programming contest like ACM-ICPC and strive to provide participants with interesting code challenges in the future.
Before the competition begins, YellowStar wants to know which teams are likely to be winners. YellowStar counted the skills of each team, including data structure, dynamic programming, graph theory, etc. In order to simplify the forecasting model, YellowStar only lists M skills and the skills mastered by each team are represented by a 01 sequence of length M. 1 means that the team has mastered this skill, and 0 does not.
If a team is weaker than other teams, this team cannot be a winner. Otherwise, YellowStar thinks the team may win. Team A(a1, a2, ..., aM ) is weaker than team B(b1, b2, ..., bM ) if ∀i ∈ [1, M], ai ≤ bi and ∃i ∈ [1, M], ai < bi.
Since YellowStar is busy preparing for the FZU Code Carnival recently, he dosen’t have time to forecast which team will be the winner in the N teams. So he asks you to write a program to calculate the number of teams that might be winners.

 

输入

Input is given from Standard Input in the following format:
N M
s1 s2 . . . sN
The binary representation of si indicates the skills mastered by teami.
Constraints
1 ≤ N ≤ 2 × 106
1 ≤ M ≤ 20
0 ≤ si < 2M

 

输出

Print one line denotes the answer.

 

样例输入

复制样例数据

3 3
2 5 6

样例输出

2

思路:题意是给你N个数,然后输出只看M位的情况下有几个队获胜,获胜的条件是

在最大的数→0的基础上,不能覆盖掉的队有几个就输出。这里是用状压dp思想来做,

先从这N个数中找出最大的数,然后从后往前依次寻找是否有在该数的基础上被覆盖

的数,如果有就将它设为-1,没有就将它存在的个数加到ans中,最后ans就代表答案。

 

当时没有写出来,可能是不知道状压dp思想,现在为了写这个题我也是专门去查了一下

状压dp是另一类非常典型的动态规划,光知道这个肯定是不行的,还得在从基础接着说

位运算:

1.’&’符号,x&y,会将两个十进制数在二进制下进行与运算(都1为1,其余为0)
然后返回其十进制下的值。例如3(11)&2(10)=2(10)。

2.’|’符号,x|y,会将两个十进制数在二进制下进行或运算(都0为0,其余为1)
然后返回其十进制下的值。例如3(11)|2(10)=3(11)。

3.’^’符号,xy,会将两个十进制数在二进制下进行异或运算(不同为1,其余
为0)然后返回其十进制下的值。例如3(11)^2(10)=1(01)。

4.’<<’符号,左移操作,x<<2,将x在二进制下的每一位向左移动两位,
最右边用0填充,也就相当于让x乘以4。

相应的,’>>’是右移操作,x>>1相当于给x/2,去掉x二进制下的最右一位。

(em.......不简单啊,是二进制运算= =)

#include<bits/stdc++.h>
using namespace std;
int dp[1<<(20)];//最大位数为20位
int main()
{
	int n,m,q;
	int maxx=0;
	cin >> n >> m;
	for(int i=1;i<=m;i++){
		cin >> q;
		dp[q]++;
		maxx=max(maxx,q);
	}
	int sum=0;
	for(int i=maxx;i>=0;i--){
		if(dp[i]!=0){
			if(dp[i]>0)//遍历时不为零的相加 
				sum+=dp[i];
			for(int j=m-1;j>=0;j--){
				if(i&(1<<j)){//判断i与j在二进制下是否相同 
					dp[i^(1<<j)]=-1;//若相同标记为-1 
				}
			}
		}
	}
	cout << sum;
	return 0;
} 

突然接触到未知领域,头大,学校的oj也崩了,看来有空得补习一下这些算法了。不然,只靠暴力可能就无法立足了= =

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值