P1441 砝码称重
题目描述
现有n个砝码,重量分别为a1,a2,a3,……,an,在去掉m个砝码后,问最多能称量出多少不同的重量(不包括0)。
输入输出格式
输入格式:输入文件weight.in的第1行为有两个整数n和m,用空格分隔
第2行有n个正整数a1,a2,a3,……,an,表示每个砝码的重量。
输出格式:输出文件weight.out仅包括1个整数,为最多能称量出的重量。
输入输出样例
3 1 1 2 2
3
说明
【样例说明】
在去掉一个重量为2的砝码后,能称量出1,2,3共3种重量。
【数据规模】
对于20%的数据,m=0;
对于50%的数据,m≤1;
对于50%的数据,n≤10;
对于100%的数据,n≤20,m≤4,m<n,ai≤100。
code
1 #include<bitset> 2 #include<cstdio> 3 #include<iostream> 4 #define f(i,x,n) for(int i=x;i<=n;++i) 5 using namespace std; 6 7 int n, m, a[21]; 8 int ans; 9 10 int bit(int x) { 11 int cnt = 0; 12 f(i, 0, n - 1) if (x & (1 << i)) cnt++; 13 return cnt; 14 } 15 16 int main() { 17 cin >> n >> m; 18 f(i, 0, n - 1) cin >> a[i]; 19 f(i, 0, (1<<n)-1) if (bit(i) == n - m) { 20 bitset<2010> t; 21 t[0] = 1; 22 f(j, 0, n - 1) if (i & (1<<j)) { 23 t = t | t << a[j]; 24 ans = max(ans, (int)t.count()); 25 } 26 } 27 cout << ans - 1 << endl; 28 return 0; 29 }
P2622 关灯问题II
题目描述
现有n盏灯,以及m个按钮。每个按钮可以同时控制这n盏灯——按下了第i个按钮,对于所有的灯都有一个效果。按下i按钮对于第j盏灯,是下面3中效果之一:如果a[i][j]为1,那么当这盏灯开了的时候,把它关上,否则不管;如果为-1的话,如果这盏灯是关的,那么把它打开,否则也不管;如果是0,无论这灯是否开,都不管。
现在这些灯都是开的,给出所有开关对所有灯的控制效果,求问最少要按几下按钮才能全部关掉。
输入输出格式
输入格式:前两行两个数,n m
接下来m行,每行n个数,a[i][j]表示第i个开关对第j个灯的效果。
输出格式:一个整数,表示最少按按钮次数。如果没有任何办法使其全部关闭,输出-1
输入输出样例
3 2 1 0 1 -1 1 0
2
说明
对于20%数据,输出无解可以得分。
对于20%数据,n<=5
对于20%数据,m<=20
上面的数据点可能会重叠。
对于100%数据 n<=10,m<=100
code
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <iostream> 5 #include <algorithm> 6 #include <map> 7 using namespace std; 8 9 const int INF = 0x3f3f3f3f; 10 int n, m, a[110][1100]; 11 int f[1100]; 12 13 int main() { 14 cin >> n >> m; 15 for (int i = 1; i <= m; ++ i) 16 for (int j = 1; j <= n; ++ j) 17 cin >> a[i][j]; 18 for (int i = 0; i < (1<<n); ++ i) f[i] = INF; 19 f[0] = 0; 20 for (int i = 0; i < (1<<n); ++ i) 21 for (int j = 1; j <= m; ++ j) { 22 int t = i; 23 for (int k = 0; k < n; ++ k) 24 if (((a[j][k+1]==1)&&!(i&1<<k)) || (a[j][k+1]==-1)&&(i&1<<k)) 25 t ^= 1 << k; 26 f[t] = min(f[t], f[i] + 1); 27 } 28 if (f[(1<<n)-1] == INF) cout << "-1" << endl; 29 else cout << f[(1<<n)-1] << endl; 30 return 0; 31 }
P1896 [SCOI2005]互不侵犯
题目描述
在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子。
注:数据有加强(2018/4/25)
输入输出格式
输入格式:只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)
输出格式:所得的方案数
输入输出样例
3 2
16
code
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <iostream> 5 #include <algorithm> 6 #define f(i, x, n) for(int i=x;i<=n;++i) 7 using namespace std; 8 9 typedef long long LL; 10 const int MAXX = 110; 11 int N, K; 12 int tot, s0, s[MAXX], num[MAXX]; 13 LL ans, dp[10][MAXX][MAXX]; 14 15 int main() { 16 cin >> N >> K; 17 f(i, 0, (1<<N)-1) { //枚举每行状态 18 if (i & (i<<1)) continue; //判断是否冲突 19 tot = 0; 20 f(j, 0, N-1) 21 if (i & (1<<j)) tot++; //统计放置数量 22 s[++s0] = i; //标记可行方案 23 num[s0] = tot; 24 } 25 dp[0][1][0] = 1; 26 f(i, 1, N) f(j, 1, s0) f(k, 0, K) 27 if (k >= num[j]) f(t, 1, s0) 28 if (!(s[t]&s[j])&&!(s[t]&(s[j]<<1))&&!(s[t]&s[j]>>1)) 29 dp[i][j][k] += dp[i - 1][t][k - num[j]]; 30 f(i, 1, s0) ans += dp[N][i][K]; 31 cout << ans << endl; 32 return 0; 33 }
P2704 [NOI2001]炮兵阵地
题目描述
司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队。一个N*M的地图由N行M列组成,地图的每一格可能是山地(用“H” 表示),也可能是平原(用“P”表示),如下图。在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队);一支炮兵部队在地图上的攻击范围如图中黑色区域所示:
如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。图上其它白色网格均攻击不到。从图上可见炮兵的攻击范围不受地形的影响。 现在,将军们规划如何部署炮兵部队,在防止误伤的前提下(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围内),在整个地图区域内最多能够摆放多少我军的炮兵部队。
输入输出格式
输入格式:第一行包含两个由空格分割开的正整数,分别表示N和M;
接下来的N行,每一行含有连续的M个字符(‘P’或者‘H’),中间没有空格。按顺序表示地图中每一行的数据。N≤100;M≤10。
输出格式:仅一行,包含一个整数K,表示最多能摆放的炮兵部队的数量。
输入输出样例
5 4 PHPP PPHH PPPP PHPP PHHP
6
code
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<iostream> 5 #include<algorithm> 6 #define f(i, x, n) for(int i=x;i<n;++i) 7 using namespace std; 8 9 const int MAXN = 100; 10 const int MAXM = 10; 11 int N, M, ans; 12 int t[MAXN], sum[(1<<10)], dp[(1<<10)][(1<<10)][3]; 13 14 void init() { 15 cin >> N >> M; 16 f(i, 0, N) f(j, 0, M) { 17 char x; cin >> x; 18 t[i] <<= 1, t[i] += (x == 'H' ? 1 : 0); 19 } 20 } 21 22 int getsum(int i) { 23 int tot = 0; 24 while(i) { if (i & 1) ++ tot; i >>= 1; } 25 return tot; 26 } 27 28 bool pd(int s) { return ((s & (s << 1)) || (s & (s << 2))); } 29 30 int main() { 31 init(); 32 f(i, 0, (1 << M)) sum[i] = getsum(i); 33 f(l, 0, (1 << M)) f(s, 0, (1 << M)) 34 if (!(l & s || l & t[0] || s & t[1] || pd(l) || pd(s))) 35 dp[l][s][1] = sum[s] + sum[l]; 36 f(i, 2, N) f(l, 0, (1 << M)) { 37 if (l & t[i - 1] || pd(l)) continue; 38 f(s, 0, (1 << M)) { 39 if (s & t[i] || l & s || pd(s)) continue; 40 f(p, 0, (1 << M)) { 41 if (p & l || p & s || p & t[i - 2] || pd(p)) continue; 42 dp[l][s][i % 3] = max(dp[l][s][i % 3], 43 dp[p][l][(i - 1) % 3] + sum[s]); 44 } 45 } 46 } 47 f(l, 0, (1 << M)) f(s, 0, (1 << M)) 48 ans = max(ans, dp[l][s][(N - 1) % 3]); 49 cout << ans << endl; 50 return 0; 51 }