标签:span line mes int names ++ mat main ons
给你一个长度为 \(n\) 的数列 \(a_1,a_2, \cdots ,a_n\)。你可以执行以下操作:选择一对 \(i,j\)(\(i \ne j\)),使 \(a_i\) 变为 \(a_i+a_j\) 并在数列中删去 \(a_j\)。问最少执行多少次操作,可以使得数列严格上升,并给出一种方案。
\(n \le 15\)
时限:7s
# include <bits/stdc++.h>
using namespace std;
const int MAXN = 15 + 5;
const int MAX1 = (1 << 15) + 5;
const int INF = 1e9;
int n;
int a[MAXN], pos[MAXN];
int sum[MAX1];
int dp[MAXN][MAXN][MAX1];
struct DPIdx
{
int i, j, mask;
} mem[MAXN][MAXN][MAX1];
int main()
{
int ncase;
scanf("%d", &ncase);
while (ncase--)
{
scanf("%d", &n);
for (int i = 0; i < n; ++i)
{
scanf("%d", &a[i]);
}
for (int mask = 0; mask < (1 << n); ++mask)
{
sum[mask] = 0;
for (int i = 0; i < n; ++i)
{
if ((1 << i) & mask)
{
sum[mask] += a[i];
}
}
for (int i = 0; i <= n; ++i)
{
for (int j = 0; j <= n; ++j)
{
dp[i][j][mask] = INF;
}
}
}
dp[0][0][(1 << n) - 1] = 0;
for (int i = 0; i < n; ++i)
{
pos[i] = i + 1;
}
DPIdx ans;
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < n; ++j)
{
for (int mask = (1 << n) - 1; mask; --mask)
{
if (dp[i][j][mask] != INF)
{
for (int sub = mask; sub; sub = (sub - 1) & mask)
{
if ((sub >> j) && sum[sub] > dp[i][j][mask] && sum[sub] < dp[i + 1][j + 1 + __builtin_ctz(sub >> j)][mask ^ sub])
{
dp[i + 1][j + 1 + __builtin_ctz(sub >> j)][mask ^ sub] = sum[sub];
mem[i + 1][j + 1 + __builtin_ctz(sub >> j)][mask ^ sub] = {i, j, mask};
if ((mask ^ sub) == 0)
{
ans = {i + 1, j + 1 + __builtin_ctz(sub >> j), mask ^ sub};
}
}
}
}
}
}
}
printf("%d\n", n - ans.i);
while (ans.i != 0)
{
DPIdx fa = mem[ans.i][ans.j][ans.mask];
for (int i = 0; i < n; ++i)
{
if (((1 << i) & (ans.mask ^ fa.mask)) && i != ans.j - 1)
{
printf("%d %d\n", pos[i], pos[ans.j - 1]);
for (int j = i + 1; j < n; ++j)
{
--pos[j];
}
}
}
ans = fa;
}
}
return 0;
}
标签:span line mes int names ++ mat main ons
原文地址:https://www.cnblogs.com/Handlip/p/12986465.html