首页 > 其他分享 >2022CCPC威海站 D - Sternhalma // 状压dp + 记忆化搜索

2022CCPC威海站 D - Sternhalma // 状压dp + 记忆化搜索

时间:2022-11-15 00:24:37浏览次数:65  
标签:10 Sternhalma 格子 2022CCPC int 状压 add state 棋子

题目来源:2022 China Collegiate Programming Contest Weihai Site D - Sternhalma

题目链接:https://codeforces.com/gym/104023/problem/D


题意

在一个\(19\)个格子的六边形棋盘上,每个格子有一个固定的权值 \(w_i\),格子上可以放置棋子。

可以进行以下两种操作:

  • 移除某个格子上的棋子,获得 \(0\) 权值.
  • 将一个棋子,以与他相邻的棋子作为跳板,跳到对称位置,跳跃后,作为跳板的棋子被移除,并获得跳板棋子所在格子的权值 \(w_i\).

有 \(t\) 组案例,每组案例给出棋子的放置情况,要求输出最大能获得的权值和。

数据范围:\(-10^6 \le w_i \le 10^6\),\(1 \le t \le 10^4\).

思路:状压dp + 记忆化搜索

由于格子的数量只有 \(19\) 个,考虑状态压缩,第 \(i\) 位为 \(0/1\) 表示第 \(i\) 个格子 无/有 棋子。

记当前状态为 \(state\),其第 \(i\) 位为 \(state_i\),其能获得的最大权值和为 \(f[state]\),则

  • 对于操作一

    若有 \(state_i = 1\),有转移 \(f[state] = max(f[state], f[state-2^i])\).

  • 对于操作二

    若有 \(state_i = 1\),记格子 \(i\) 做跳板时,跳跃前后的格子为 \(a\),\(b\),若有\(state_a = 1\ and\ state_b = 0\),则有转移 \(f[state] = max(f[state], f[state - 2^i - 2^a + 2^b])\).

为了方便转移,我们可以先将每个格子做跳板时,合法的跳跃前后的格子对,预处理出来。

因为格子的权值固定,因此可以用记忆化搜索。

时间复杂度:\(O(t·n + 2^n)\),其中 \(n=19\).

代码

#include <bits/stdc++.h>
#define endl '\n'
using namespace std;

const int N = 19;

int w[N], f[1 << N], vis[1 << N];
vector<pair<int,int>> v[N];  // v[i]:格子i作为跳板时,合法的跳跃前后格子
 
// 跳板格子,以及跳跃前后的两个格子
void add(int mid, int a, int b) 
{
    v[mid].push_back({a, b});
    v[mid].push_back({b, a});
}

int dfs(int state)
{
    if(vis[state]) return f[state];

    // Remove 
    for(int i = 0; i < N; ++ i) {
        if(!(state >> i & 1)) continue;
        f[state] = max(f[state], dfs(state - (1 << i)));
    }

    // Remove by jumping
    for(int i = 0; i < N; ++ i) {
        if(!(state >> i & 1)) continue;
        for(auto p : v[i]) {
            int a = p.first, b = p.second;
            if(!(state >> a & 1) || (state >> b & 1)) continue;
            f[state] = max(f[state], dfs(state - (1 << i) - (1 << a) + (1 << b)) + w[i]);
        }
    }

    vis[state] = 1;
    return f[state];
}

int main()
{
    cin.tie(0);
    ios::sync_with_stdio(false);

    for(int i = 0; i < N; ++ i) cin >> w[i];
    memset(f, -0x3f, sizeof f);
    f[0] = 0, vis[0] = 1;

    add(1, 0, 2);
    add(3, 0, 7);
    add(4, 0, 9), add(4, 1, 8), add(4, 3, 5);
    add(5, 1, 10), add(5, 2, 9), add(5, 4, 6);
    add(6, 2, 11);
    add(8, 3, 13), add(8, 4, 12), add(8, 7, 9);
    add(9, 4, 14), add(9, 5, 13), add(9, 8, 10);
    add(10, 5, 15), add(10, 6, 14), add(10, 9, 11);
    add(12, 7, 16);
    add(13, 8, 17), add(13, 9, 16), add(13, 12, 14);
    add(14, 9, 18), add(14, 10, 17), add(14, 13, 15);
    add(15, 11, 18);
    add(17, 16, 18);

    int test;
    cin >> test;
    while(test--) {
        string s, t;
        for(int i = 0; i < 5; ++ i) cin >> t, s += t;
        int state = 0;
        for(int i = 0; i < N; ++ i) {
            if(s[i] == '#') state += 1 << i;
        }
        cout << dfs(state) << endl;
    }

    return 0;
}

标签:10,Sternhalma,格子,2022CCPC,int,状压,add,state,棋子
From: https://www.cnblogs.com/jakon/p/16891052.html

相关文章

  • 广州2022CCPC补题
    IInfection知识点:树上背包第一次写树上背包的题目,没想到就是在区域赛中神奇的是树上背包的复杂度,看起来是\(O(n^3)\),但是实际计算只有\(O(n^2)\)学会树上背包后可......
  • P3226 [HNOI2012]集合选数(状压 DP)
    P3226[HNOI2012]集合选数要求选出集合\(S\)满足如果\(x\)选择了,\(2x\)和\(3x\)都不能选择。求\(\{1,2,\dots,n\}\)的符合要求的子集数量。\(n\le10^5\)。......
  • 2022CCPC威海 D. Sternhalma(记忆化搜索/状压)
    题意大概是给定一个19个格子的六边形棋盘,每个位置有一个分数,每次操作可以拿走一个棋子(不得分)或者将当前棋子跳过相邻的一个棋子(得分为跳过的棋子所在位置的分数)且将跳过的......
  • 2022CCPC威海J. Eat, Sleep, Repeat(博弈/思维)
    题目大意是给定长度为n的数组a,两个人轮流从中选一个正数将其减1。且有k个限制形如\(limit_{x_i}=y_i\),即\(x_i\)在数组中最多出现\(y_i\)次。判负的情况为:数组全为0......
  • CF1463F Max Correct Set(取小样法+状压 DP)
    CF1463FMaxCorrectSet要求选出集合\(U=\{1,2,3,\dots,n\}\)的一个子集\(S\),满足:如果\(a\inS\)并且\(b\inS\),那么\(|a-b|\not={x}\)并且\(|a-b|\not=......
  • CF1342F Make It Ascending(状压+求过程->求结果)
    CF1342FMakeItAscending给予一个包含\(n\)个元素的数组\(a\),你可以进行以下操作:选择两个不同的元素\(a_i,a_j\)(\(1\lei,j\len\),\(i\nej\))将\(a_j\)的......
  • 2022CCPC(桂林)
    我的首站本来想着练练手拿铜牌血赚打铁不亏结果保底铜牌要是G题做出来应该可以冲击一下银牌https://codeforces.com/gym/104008A.Lily签到题:所有不在L旁的字符......
  • 【CF1292F】Nora's Toy Boxes(状压DP)
    考虑将点分为$A,B$两类。其中$[x\inA]\iff\exists_{y\neqx},y|x$。那么我们删去的点只可能在$B$类中,且当前$x\inB$可删当且仅当存在$y\inB,z\inA$使得$z|x......
  • 【XSY3896】相似(dp套dp,状压)
    题面相似题解可以发现,\(S\)和\(T\)相似,等价于它们的最长公共子序列长度至少为\(n-k\)。首先考虑如何求出两个字符串的\(\text{LCS}\)(最长公共子序列)。考虑dp:......
  • 【XSY3513】Multiple of Nine(状压DP)
    题意:转化后变为:给一张\(n\)个点的图,你需要给每个点染上\([1,k]\)中的某个颜色,图上有\(m\)条边,每条边\((u,v)\)有两种边权\(w_1\)(当\(u,v\)颜色相同时)和\(w_2\)......