P3943 星空

P3943

思维好题

接下来, 您将看到 :

  • 差分(??!)
  • bfs
  • 状压dp

第一波操作(差分):

d[i] = a[i] ^ a[i-1]

例子: 10011100 (0表示不亮, 1为亮了) 它的"差分"数组为 11010010

吃瓜群众: 为什么要这么表示

let's 模拟 it

原状态 : 10011100 -> 11010010 将第四盏到第六盏搞一下 10000000 -> 11000000

fa♂现了没有, 差分数组位置4, 7改变, 因为异或使4到6同时改变, 他们相邻两个异或值不会改变

而3和4, 6和7中有一个值改变, 那么他们异或值也会改变

同样的, 如果操作第四盏到第七盏, 发现差分数组位置4的1移到了位置8(汝可模拟得知)

所以我们要求出所有的1,移动最少几次和另一个1配对

第二波操作(bfs):

预处理出每一个1到其他1的距离, bfs就行啦

第三波操作(状压dp):

设计状态S, f[S]表示消除点集S至少要操作多少次

f[S] = min(f[S], f[S-'两个点'] + 两点相消要走多少次);

代码:

#include
#include
#include
#include
#include
using namespace std;
const int N = 40050;
int b[70], n, m, k;
int a[50], f[N];
int pos[50], g[1005000];
inline int to(int x) {
    return 1 << x;
}
queue q;
int main() {
    cin >> n >> k >> m;
    for (int i = 1;i <= k; i++) 
        cin >> a[i];
    sort(a + 1,a + k + 1);
    int cnt = 1;
    pos[1] = a[1];
    for (int i = 2;i <= k; i++) 
    if (a[i] != a[i-1] + 1) {
        pos[++cnt] = a[i-1]+1;
        pos[++cnt] = a[i];
    }
    pos[++cnt] = a[k]+1;
    for (int i = 1;i <= m; i++) cin >> b[i];
    memset(f, 0x3f, sizeof(f));
    f[0] = 0;
    q.push(0);
    while (q.size()) {
        int x = q.front(); q.pop();
        for (int i = 1;i <= m; i++) {
            int y = x + b[i];
            if (y <= n && f[y] > n) {
                f[y] = f[x] + 1;
                q.push(y);
            }
            y = x - b[i];
            if (y > 0 && f[y] > n) {
                f[y] = f[x] + 1;
                q.push(y);
            }
        }
    }       
    memset(g, 0x3f, sizeof(g));
    g[0] = 0;
    for (int i = 1;i < 1 << cnt; i++) {
        int tmp = 0;
        for (int j = 1;j <= cnt; j++) 
            if (i & to(j-1)) tmp++;
        if (tmp & 1) continue;
        for (int j = 1;j <= cnt; j++) 
            if (i & to(j-1))
            for (int k = j + 1;k <= cnt; k++) 
                if (i & to(k-1)) 
                    g[i] = min(g[i], g[i^to(k-1)^to(j-1)] + f[pos[k]-pos[j]]);
    }
    cout << g[(1 << cnt) - 1] << endl;
    return 0;
}

你可能感兴趣的:(P3943 星空)