2020 CCPC 长春 J. Abstract Painting(状压dp)
Posted issue是fw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2020 CCPC 长春 J. Abstract Painting(状压dp)相关的知识,希望对你有一定的参考价值。
顺序考虑区间上的每个点作为圆的右端点,定义 f [ i ] f[i] f[i]表示 [ 0 , i ] [0,i] [0,i]的方案数
考虑 i i i点之前有一个直径为 [ x − r , x + r ] [x-r,x+r] [x−r,x+r]的圆( x + r < i x+r<i x+r<i)
当以 i i i为右端点放直径为 [ l , i ] [l,i] [l,i]的圆时, 显然 l l l不能是 [ x − r + 1 , x + r − 1 ] [x-r+1,x+r-1] [x−r+1,x+r−1]中的任意一点
只要满足这个条件,交点数一定小于等于 1 1 1
然后注意到半径不超过 5 5 5,所以以 i i i为右端点的圆只需要考虑 [ i − 10 , i − 1 ] [i-10,i-1] [i−10,i−1]的点是否能放
那么定义 f [ i ] [ j ] f[i][j] f[i][j]表示 [ 1 , i ] [1,i] [1,i]中 [ i − 10 , i ] [i-10,i] [i−10,i]的点空余状态为 j j j(可以给后续圆放为 0 0 0,不能为 1 1 1)
那么每次枚举以 i i i为右端点的圆的所有半径组合 1 , 2 , 3 , 4 , 5 1,2,3,4,5 1,2,3,4,5(状压枚举)
判断一下是不是包括了这个点必须放的圆
然后枚举 f [ i − 1 ] [ q ] f[i-1][q] f[i−1][q],判断是否产生冲突转移
(写起来细节非常多)
代码中第 0 0 0位二进制表示位置 i i i,第 1 1 1位二进制表示位置 i − 1 i-1 i−1,以此类推
#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e5+19;
const int mx = (1<<11)-1;
const int mod = 1e9+7;
int n,k,f[5009][1<<12],ned[5009];
int get(int r)
{
return mx&(((1<<(2*r))-2));
}
int main()
{
cin >> n >> k;
for(int i=1;i<=k;i++)
{
int c,r; scanf("%d%d",&c,&r);
ned[c+r] |= (1<<(r*2));
}
f[0][mx-1] = 1;
for(int i=1;i<=n;i++)
{
for(int q=0;q<(1<<5);q++)
{
int v = 0, zz = 0, maxx = 0;//v表示这个状态下覆盖点的状态,zz表示这个状态下端点的状态,maxx表示选择的最大圆
for(int w=0;w<5;w++)
if( (q>>w)&1 ) v |= get(w+1), zz |= (1<<(2*w+2)), maxx = w+1;
if( (zz&ned[i])!=ned[i] || maxx*2>i ) continue;
for(int j=0;j<(1<<11);j++)
{
int now = ((j<<1)&mx);
if( now&zz ) continue;
now = now | v;
f[i][now] = ( 1ll*f[i][now]+f[i-1][j] )%mod;
}
}
}
long long ans = 0;
for(int i=0;i<(1<<11);i++) ans = ( ans+f[n][i] )%mod;
cout << ans;
}
以上是关于2020 CCPC 长春 J. Abstract Painting(状压dp)的主要内容,如果未能解决你的问题,请参考以下文章
2020 ccpc长春 D. Meaningless Sequence(按位启发式合并)
2020CCPC 长春 L. Coordinate Paper(思维,构造)
2020第6届中国大学生程序设计竞赛CCPC长春站, 签到题3题