如果要求字符串s的子集 s是只由A和B组成的,则可以把A看作1 B看作0 进而把s转换成一个由1和0组成的二进制数 S
则求S的子集就可以用以下代码来实现
int len = s.size() for(int i=1; i< 1<<len; i++) { num[cnt++] = S & i; }
因为从0到1<<len-1 包含了由1和0组成的所有情况 又因为&的性质 所以可以实现求子集
例题:http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?cid=820&pid=1001
#include <iostream> #include <cstdio> #include <sstream> #include <cstring> #include <map> #include <set> #include <vector> #include <stack> #include <queue> #include <algorithm> #include <cmath> #define rap(i, a, n) for(int i=a; i<=n; i++) #define MOD 2018 #define LL long long #define ULL unsigned long long #define Pair pair<int, int> #define mem(a, b) memset(a, b, sizeof(a)) #define _ ios_base::sync_with_stdio(0),cin.tie(0) //freopen("1.txt", "r", stdin); using namespace std; const int maxn = 10010, INF = 0x7fffffff; int num[maxn], temp[maxn], vis[maxn]; int n, m, k; int main() { int T, kase = 0; cin>> T; while(T--) { int ans = 0; mem(num, 0); mem(vis, 0); cin>> n >> m >> k; string str; rap(i, 1, n) { cin>> str; rap(j, 0, m-1) { if(j != 0) num[i] <<= 1; if(str[j] == 'A') num[i] ^= 1; } // cout<< num[i] <<endl; } int res = 0; for(int i=1; i < 1<<m; i++) { mem(vis, 0); mem(temp, 0); int cnt = 0; res = 0; for(int j=1; j<=n; j++) { int t = num[j] & i; if(!vis[t]) temp[cnt++] = t; vis[t]++; } for(int j=0; j<cnt; j++) { for(int q=j+1; q<cnt; q++) { res += vis[temp[j]] * vis[temp[q]]; } } if(res >= k) ans++; // cout<< res <<endl; } printf("Case #%d: %d\n", ++kase, ans); } return 0; }
当然二进制也可以用于全排列
例题
hdu 1074import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.Scanner; public class Main{ final static int maxn = 1<<16; final static int INF = 0xfffffff; public static int n; public static class node{ String name = new String(); int d,c; node(String name, int d, int c) { this.name = name; this.d = d; this.c = c; } } public static ArrayList<node> list = new ArrayList<>(); public static int[] pre = new int[maxn]; public static void print(int step) //输出函数 类似 bfs最短路输出路径 { if(step == 0) return; int t = 0; for(int i=0;i<n;i++) { if((step & (1<<i)) != 0 && (pre[step] & (1<<i)) == 0) { t = i; break; } } print(pre[step]); System.out.println(list.get(t).name); } public static void main(String[] args) { Scanner cin = new Scanner(System.in); int cnt = 0; int T = cin.nextInt(); while(T-- != 0) { list.clear(); int[] dp = new int[maxn]; Arrays.fill(pre, 0); n = cin.nextInt(); for(int i=0;i<n;i++) { String name = cin.next(); int d = cin.nextInt(); int c = cin.nextInt(); list.add(new node(name,d,c)); } Arrays.fill(dp, INF); dp[0] = 0; for(int i=0;i < 1<<n;i++) //已经做完的作业 { for(int j=0;j<n;j++) // 即将要做的作业 { if((i & (1<<j)) != 0) continue; int s = 0; for(int k=0;k<n;k++) //求出已经做完的作业的所耗费的时间 { if((i & (1<<k)) != 0) { s += list.get(k).c; } } if(s + list.get(j).c > list.get(j).d) //求出即将要做的作业是否超时 s = s + list.get(j).c - list.get(j).d; else s = 0; if(dp[i|(1<<j)] > dp[i] + s) { dp[i|(1<<j)] = dp[i] + s; pre[i|(1<<j)] = i; } } } System.out.println(dp[(1<<n)-1]); print((1<<n)-1); } } }