2021牛客寒假算法基础集训营6 G.机器人 (状压dp+__int128)

传送门

题意

有 n 个机器人,每个机器人会读入一个 x ,并返回 ax+b 。

现在银临姐姐手里有一个数 x ,她想将机器人按某种顺序排列,使得最终返回得到的 x 尽可能大。

对于所有的数据,1 ≤ n , x , a i , b i ≤ 20 \le n,x,a_i,b_i\le20 n,x,ai,bi20

分析

状压dp裸题:
f [ i ] f[i] f[i]表示状态为 i i i(i中第j位为0表示还没用过第j个机器人,为1时表示已经用过了第j个机器人,j=[0~n-1])时,结果的最大值。
状态更新举例:
f [ ( 111 ) 2 ] f[(111)_2] f[(111)2]要从 f [ ( 011 ) 2 ] , f [ ( 101 ) 2 ] , f [ ( 110 ) 2 ] f[(011)_2],f[(101)_2],f[(110)_2] f[(011)2],f[(101)2],f[(110)2]三个状态更新过来。
f [ ( 111 ) 2 ] = m a x ( a [ 2 ] ∗ f [ ( 011 ) 2 ] + b [ 2 ] , a [ 1 ] ∗ f [ ( 101 ) 2 ] + b [ 1 ] , a [ 0 ] ∗ f [ ( 110 ) 2 ] + b [ 0 ] ) f[(111)_2]=max(a[2]*f[(011)_2]+b[2],a[1]*f[(101)_2]+b[1],a[0]*f[(110)_2]+b[0]) f[(111)2]=max(a[2]f[(011)2]+b[2],a[1]f[(101)2]+b[1],a[0]f[(110)2]+b[0])
最终答案就是 f [ ( 1111...11 ) 2 ] f[(1111...11)_2] f[(1111...11)2](n个1)

但是动手算算上界会超longlong。
调了好久的高精都有问题(板子是很久之前写的,现在看起来当时写的并不好),最后__int128水过去了。

关于__int128

仔细整理一下__int128,还挺好用的,我电脑上可以正常使用,不存在网上说的Linux才能用。
但是:
1.__int128的上界是3.4e38,太大了还是不行。
2.要手动实现输入输出函数。
3.位运算的时候要注意写法(被坑过)。

代码

#include <bits/stdc++.h>

using namespace std;
//-----pre_def----
const double PI = acos(-1.0);
const int INF = 0x3f3f3f3f;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
#define fir(i, a, b) for (int i = (a); i <= (b); i++)
#define rif(i, a, b) for (int i = (a); i >= (b); i--)
#define endl '\n'
#define init_h memset(h, -1, sizeof h), idx = 0;
#define lowbit(x) x &(-x)

//---------------
const int N = 23;

int n, x;
int a[N], b[N];
__int128 f[1 << 21];
inline void print(__int128 x)
{
    
    
    if (x < 0)
    {
    
    
        putchar('-');
        x = -x;
    }
    if (x > 9)
        print(x / 10);
    putchar(x % 10 + '0');
}

int main()
{
    
    
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    int StartTime = clock();
#endif
    scanf("%d%d", &n, &x);
    f[0] = x;
    fir(i, 0, n - 1)
    {
    
    
        scanf("%d%d", &a[i], &b[i]);
    }
    for (int i = 1; i <= (1 << n) - 1; i++)
    {
    
    
        for (int j = 0; j < n; j++)
        {
    
    
            if ((i >> j) & 1)
            {
    
    
                f[i] = max(f[i], f[i - (1 << j)] * a[j] + b[j]);
            }
        }
    }
    print(f[(1 << n) - 1]);
#ifndef ONLINE_JUDGE
    printf("Run_Time = %d ms\n", clock() - StartTime);
#endif
    return 0;
}

一道相似的高精+dp题目

猜你喜欢

转载自blog.csdn.net/sancpp/article/details/114051248