luogu P1896 [SCOI2005]互不侵犯

去tm插头dp

数据范围这么,又要求,显然上dp

\(f[i][j][k]\)表示放到第\(i\)行,总共放了\(j\)个那啥,第\(i\)行的格子状态为\(k\)的方案

先预处理出一行内状态的放置个数和格子状态,因为那啥占据周围一圈的格子,所以转移时前后两行格子状态没有交集的状态转移

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<ctime>
#include<queue>
#include<map>
#define LL long long
#define il inline
#define re register

using namespace std;
const LL mod=1000000007;
il LL rd()
{
    re LL x=0,w=1;re char ch;
    while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return x*w;
}
LL nn,n,kk,f[10][85][1100],ans;
LL nu[1100],b[1100],tt; //nu是某个状态的棋子数量,b为相对应的格子状态
bool v[1100];
il void init(int i,int j,int k)
{
  if(v[k]) return;
  ++tt;
  nu[tt]=j,b[tt]=k;
  v[k]=true;
  for(;i<=n;i++)
    init(i+2,j+1,k|(1<<(i-1))|(i<n?(1<<i):0));    //对于某个棋子所在行以及上(没什么用),下的行,棋子所在列和左边(没什么用),右边都被占了
}


int main()
{
  freopen("xzz.in","r",stdin);
  freopen("xzz.out","w",stdout);
  n=rd(),kk=rd();
  nn=1<<n;
  init(1,0,0);
  for(int i=1;i<=tt;i++) f[1][nu[i]][b[i]]=1;
  for(int i=2;i<=n;i++)
    {
      for(int j=1;j<=tt;j++)
        for(int k=1;k<=tt;k++)
         {
          if((b[j]|b[k])!=b[j]+b[k]) continue;
          for(int l=nu[j];l<=kk;l++)
           f[i][l][b[j]]+=f[i-1][l-nu[j]][b[k]];
         }
    }
  for(int j=1;j<=tt;j++) ans+=f[n][kk][b[j]];
  printf("%lld\n",ans);
  return 0;
}
语文好差啊嘤嘤嘤

转载于:https://www.cnblogs.com/smyjr/p/9408631.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值