[HDU 5691] Sitting in Line

题意简述:

给出一个n 代表n个数 每个数有 v(代表数的值) pos(代表数的位置 -1表示任意位置)

要求将这n个数进行排列 使得不违背位置关系

求所有相邻两个数乘积和的最大值

思路浅析:

设dp [ i ] [ j ]表示上一个用的是 i 的数并且状态为 j 的情况时的最优解,显然之后在从左往右填入数字的过程中,若当前位置已经有必填的数,那么直接状态转移,否则选一个可以放在任意位置的数,由于 i 已经确定,所以结果只会受到决策影响,具有无后效性

#include <bits/stdc++.h>
#define inf 0x7fffffff
using namespace std;
const int N = 20;

int getnum(int x)
{
    int cnt = 0;
    while (x)
    {
        cnt += x & 1;
        x >>= 1;
    }
    return cnt;
}

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while (!isdigit(ch))
        f = (ch == '-') ? -1 : 1, ch = getchar();
    while (isdigit(ch))
        x = x * 10 + (ch - '0'), ch = getchar();
    return x * f;
}

int n, T, cas;
int a[N], p[N];
int dp[N][1 << N];
int main()
{
    int cas = 0;
    int T;
    T = read();
    while (T--)
    {
        n = read();
        for (int i = 0; i < n; i++)
            a[i] = read(), p[i] = read();

        for (int i = 0; i < n; i++)
            for (int j = 0; j < (1 << n); j++)
                dp[i][j] = -inf;

        for (int i = 0; i < n; i++)
            if (p[i] == -1 || p[i] == 0)
                dp[i][1 << i] = 0;
        for (int sta = 0; sta < (1 << n); sta++)
            for (int i = 0; i < n; i++) //前一个
                if (dp[i][sta] > -inf) /* 如果可以被继承 */
                    for (int j = 0; j < n; j++)
                        if (p[j] == -1 || p[j] == getnum(sta))
                        {
                            if (sta & (1 << j))
                                continue;
                            if (i == j)
                                continue;
                            int now = sta | (1 << j);
                            dp[j][now] = max(dp[j][now], dp[i][sta] + a[j] * a[i]);
                        }

        int ans = -inf;
        for (int i = 0; i < n; i++)
            ans = max(ans, dp[i][(1 << n) - 1]);
        printf("Case #%d:\n", ++cas);
        cout << ans << endl;
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/wyctstf/p/11344623.html