J. Abstract Painting (2020 CCPC 长春)

J. Abstract Painting

tag:dp

题目链接

题意:

有个很抽象的人要画一幅抽象画,这个抽象画只需要画圆圈就完事了(我上我也行)
需要满足以下条件

  • 圆心都必须在x轴上的[1,n]上,且必须都是整数点。(2≤n≤10^3)
  • 圆的半径为整数,只能取{1,2,3,4,5}。
  • 圆和圆之间最多一个交点,即要么相切要么不相交。
    此外原本x轴上就有一些圆
    我们需要求可行的绘画方案数(ps: 一个圆都不画也算一种方案)

做法:

这道题的做法主要有区间dp和状压dp两种,我认为区间dp好写很多,下面我们只讲区间dp的做法
首先我们可以将圆抽象为区间,圆心x,半径r,我们可以表示为[x-r,x+r]
如果两个区间交叉着了,那么显然不合法
在进行区间dp之前我们需要两个数组来辅助,fix[l][r]标记原本就有的圆,ban[l][r]标记不合法的圆
我们设 dp[l][r][0/1] 表示区间l,r之内的方案数,0、1表示这些方案中存不存在圆[l,r]
首先我们可以想到一个很简单的转移,如果我们可以画出一个[l,r]的圆,那么显然 dp[l][r][1] = dp[l][r][0]
剩下的转移方法就比较细节,请配合代码注释食用

代码:

#define fst std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout << std::fixed << std::setprecision(20)
#define le "\n"
#define ll long long 
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+50;
const int mod=1e9+7;
bool fix[1050][1050],ban[1050][1050];//标记原本就有的圆,
ll dp[1050][1050][2];

int main(){
    int n,k,x,r;
    cin>>n>>k;
    for(int i=1;i<=k;i++){
        cin>>x>>r;
        fix[x-r][x+r]=true;

        for(int i=0;i<x-r;i++){
            for(int j=x-r+1;j<x+r;j++){
                ban[i][j]=true;
            }    
        }

        for(int i=x-r+1;i<x+r;i++){
            for(int j=x+r+1;j<=n;j++){
                ban[i][j]=true;
            }
        }
    }
    
    for(int i=0;i<n;i++) dp[i][i+1][0]=1;//最小的圆是[i,i+2]
    
    for(int len=2;len<=n;len++){
        for(int l=0,r=len;r<=n;l++,r++){
            if(ban[l][r]) continue;

            dp[l][r][0]=(dp[l+1][r][0]+dp[l+1][r][1])%mod; 
            //首先继承一下 [l+1,r] 的方案数,现在左边多了一个点l,我们固定左端点l,枚举右端点来更新状态
            for(int m=l+2;m<=min(l+10,r);m+=2){
                dp[l][r][0]=(dp[l][r][0]+dp[l][m][1]*(dp[m][r][0]+dp[m][r][1]))%mod;
            }
            
            if((r-l)%2==0&&r-l<=10) dp[l][r][1]=dp[l][r][0]; 
            //能画个左右端点为l,r的圆,那就直接套上去,此时画或者不画方案数一致

            if(fix[l][r]) dp[l][r][0]=0;
            //原本就有画在l,r的园,不可能不画
        }
    }
    
    cout<<(dp[0][n][0]+dp[0][n][1])%mod<<le;
    
    return 0;
} 
posted @ 2023-02-16 10:58  touchfishman  阅读(49)  评论(0)    收藏  举报