有一说一,这场裸题签到题真不少。
这场稍微把G拿出来说一下。
G是状压dp的入门题,恶心就恶心在数据范围能到2021。
这道题给了我们20组运算,我们用(1<<21)来模拟状态。
为什么用(1<<21):1<<21用二进制就是1000000…000(21个0),所以1<<21-1就有20个1。
我们可以用0表示还未使用此个数据。用1表示已经用过这个数据。
我们设置一个dp[1<<21],故转移就有
dp[ i | (1 << k) ] = max(dp[ i | ( 1 << k) ] ,dp[ i ]*a[ i ] + b[ i ] )
这里 ‘|’ 表示使用掉第k组数据,使二进制k位为1。
i 从 0遍历到(1<<21-1),即从一个都不取遍历到全取完的状态。
主要是这毒瘤的数据,用了java的BigInteger。c++的_int128也是可以的,文章最后有初版的c++代码。
import java.math.BigInteger;
import java.util.Scanner;
public class Main {
public static BigInteger[] a = new BigInteger[50];
public static BigInteger[] b = new BigInteger[50];
public static BigInteger[] dp = new BigInteger[1<<21];
public static void main(String[] args) {
BigInteger n,m;
Scanner in = new Scanner(System.in);
n = new BigInteger(in.next());
m = new BigInteger(in.next());
for (int i = 0;i < n.intValue();i++)
{
String s1,s2;
s1 = in.next();
s2 = in.next();
a[i] = new BigInteger(s1);
b[i] = new BigInteger(s2);
}
for (int i = 0;i < (1 << n.intValue());i++)
dp[i] =new BigInteger("1");
for (int i = 0; i < n.intValue(); i++) {
dp[1 << i] = a[i].multiply(m).add(b[i]);
}
for (int i = 0; i < (1 << n.intValue()); i++) {
for (int k = 0; k < n.intValue(); k++) {
if (((i >> k) & 1) == 0) {
dp[i | (1 << k)] = dp[i | (1 << k)].max(dp[i].multiply(a[k]).add(b[k])) ;
}
}
}
System.out.println(dp[(1 << n.intValue()) - 1]);
}
}
怕有些人还没学java,这里放一份没有改_int128的c++代码,可以自己动手改改
#include <bits/stdc++.h>
using namespace std;
//#define ACM_LOCAL
#define fi first
#define se second
#define il inline
#define re register
typedef long long ll;
typedef pair<int, int> PII;
typedef unsigned long long ull;
const int N = 2e5 + 10;
const int M = 1e6 + 10;
const int INF = 1e9 + 5;
const double eps = 1e-5;
const int MOD = 998244353;
ll a[N], b[N];
ll dp[1 << 21];
void solve() {
ll n, m;
cin >> n >> m;
for (int i = 0; i < n; i++) {
cin >> a[i] >> b[i];
}
for (int i = 0; i < n; i++) dp[1 << i] = a[i] * m + b[i];
for (int i = 0; i < (1 << n); i++) {
for (int k = 0; k < n; k++) {
if (!(i >> k & 1)) {
dp[i | (1 << k)] = max(dp[i | (1 << k)], dp[i] * a[k] + b[k]);
}
}
}
cout << dp[(1 << n) - 1] << endl;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
#ifdef ACM_LOCAL
freopen("input", "r", stdin);
freopen("output", "w", stdout);
#endif
solve();
}