#include<bits/stdc++.h> usingnamespace std; #define ll long long constint N = 2e5 + 10; constint INF = 0x3f3f3f3f; int n, m, k; char mz[20][1010]; int U[1010], D[1010], tot, cnt[1010]; int ans = INF; int sum[20][1010]; boolcheck(){ for (int i = 1; i <= tot; i++) { if (cnt[i] > k)returnfalse; } returntrue; } intmain(){ scanf("%d%d%d", &n, &m, &k); for (int i = 1; i <= n; i++)for (int j = 1; j <= m; j++) { scanf(" %c", &mz[i][j]); sum[i][j] = mz[i][j] - '0'; } for (int j = 1; j <= m; j++) { for (int i = 1; i <= n; i++) { sum[i][j] += sum[i - 1][j]; } } for (int i = 0; i < (1 << (n - 1)); i++) { int u = 1, d = 1; int tmp = 0; for (int j = 0; j < 10; j++) { if (i&(1 << j))tmp++; } tot = 0; while (u <= n) { for (; d < n && !(i&(1 << (d - 1))); d++); U[++tot] = u; D[tot] = d; u = d + 1; d = u; } bool flg = 1; for (int j = 1; j <= m; j++) { for (int c = 1; c <= tot; c++) { cnt[c] = sum[D[c]][j] - sum[U[c] - 1][j]; } if (!check()) { flg = 0; break; } } if (!flg)continue; int l = 1, r = 1; while (l <= m) { for (int j = 1; j <= tot; j++)cnt[j] = 0; while (r <= m) { for (int j = 1; j <= tot; j++) { cnt[j] += sum[D[j]][r] - sum[U[j] - 1][r]; } if (!check())break; r++; } l = r; tmp++; } ans = min(ans, tmp - 1); } cout << ans << endl; return0; }
F - Knapsack for All Segments
题意:给定数列 A 和正整数 S,定义 f(L,R) 表示 [L,R] 中和为 S 的子序列的个数。求 ∑i=1n∑j=inf(i,j),即所有区间的 f 值之和。