码迷,mamicode.com
首页 > 其他好文 > 详细

CF1342F Make It Ascending

时间:2020-05-29 12:18:52      阅读:67      评论:0      收藏:0      [点我收藏+]

标签: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;
}

CF1342F Make It Ascending

标签:span   line   mes   int   names   ++   mat   main   ons   

原文地址:https://www.cnblogs.com/Handlip/p/12986465.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!