原题
思路
前缀和处理人数, 10表示是否有序,经行状压,枚举当前状态最后一个有序的乐队。
#include <algorithm>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <list>
#include <map>
#include <iostream>
#include <iomanip>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
#define LL long long
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f
#define PI 3.1415926535898
#define F first
#define S second
#define endl '
'
#define lson rt << 1
#define rson rt << 1 | 1
#define f(x, y, z) for (int x = (y), __ = (z); x < __; ++x)
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
using namespace std;
const int maxn = 1e5 + 7;
const int maxm = 25;
const int mod = 1e9 + 7;
int n, m;
int bel[maxn];
int sum[maxn][maxm];
int dp[1 << 21];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n >> m;
_rep(i, 1, n)
{
cin >> bel[i];
_rep(j, 1, m) sum[i][j] = sum[i - 1][j];
sum[i][bel[i]]++;
}
_rep(i, 1, 1 << m) dp[i] = inf;
f(i, 1, 1 << m)
{
int len = 0;
_rep(j, 1, m) if (i & (1 << j - 1)) len += sum[n][j];
_rep(j, 1, m)
{
if (!(i & (1 << j - 1))) continue;
int tmp = 1 << j - 1;
dp[i] = min(dp[i], dp[i ^ tmp] + sum[n][j] - sum[len][j] + sum[len - sum[n][j]][j]);
}
}
cout << dp[(1 << m) - 1] << endl;
}
同类型题
#include <algorithm>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <list>
#include <map>
#include <iostream>
#include <iomanip>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
#define LL long long
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f
#define PI 3.1415926535898
#define F first
#define S second
#define endl '
'
#define lson rt << 1
#define rson rt << 1 | 1
#define f(x, y, z) for (int x = (y), __ = (z); x < __; ++x)
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
using namespace std;
const int maxn = 1e5 + 7;
const int maxm = 25;
const int mod = 1e8;
int n, m;
int dp[1 << 16];
int coin[17], a[maxn], sum[maxn];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin >> m >> n;
int ans = inf, tot = 0;
_rep(i, 1, m)
{
cin >> coin[i];
tot += coin[i];
}
_rep(i, 1, n)
{
cin >> a[i];
sum[i] = sum[i - 1] + a[i];
}
sum[n + 1] = 1e9;
f(i, 0, 1 << m)
{
int tmp = 0;
f(j, 0, m) if (i & (1 << j)) tmp += coin[j + 1];
f(j, 0, m)
{
if (i & (1 << j))
{
int temp = dp[i ^ (1 << j)];
int nxt = upper_bound(sum + temp, sum + n + 1, coin[j + 1] + sum[temp]) - sum;
nxt -= 1;
dp[i] = max(dp[i], dp[i ^ (1 << j)] + nxt - temp);
if (dp[i] == n) ans = min(ans, tmp);
}
}
}
cout << ((tot - ans >= 0)?tot - ans: -1)<< endl;
}