首页 > 其他分享 >棋子--状态压缩dp

棋子--状态压缩dp

时间:2023-05-31 19:04:25浏览次数:29  
标签:满足条件 状态 -- 摆放 int 棋子 long dp


题目描述:在一个N*N的棋盘上放棋子,每一个棋子的上下左右都没有棋子,也就是不相邻,一共有多少种放法?(N <= 8)


sample_input

0
1
3

sample_output
1
2
63


分析:首先,我们可以逐行来摆放这些棋子,这样我们会发现,每一行的摆放状态只和上一行有关,这样我们可以采用递推

的方式来解决。


假设f[i][j]为第i行的摆放状态为j时的摆放总数(j表示所有满足条件的单行状态,如01001二进制表示0表示不放,1表

示放),那么第i+1行的值就可以根据第i行来求,即f[i+1][k]=∑f[i][j] (j&k==0表示这两行不会产生冲突)
     

例如第i行摆放状态为 00101,则第i+1行的状态10010满足条件.


最后我们得到状态转移方程
     

f[i][j]=∑f[i-1][k](k表示所有与j不冲突的状态,f[0][0]=1;



#include <cstdio>
#include <iostream>
#include <cstring>

using namespace std;

int s[1111];          /**记录所有满足条件的单行表示*/
long long f[11][1111];/**f[i][j]表示第i行为第j种状态的摆放总数*/
int n,m;              /**n表示棋盘大小,m表示满足条件的状态数*/
long long ans;        /**记录答案*/

bool ok(int x   )/**判断x是否满足条件*/
{
    while(x)  /**将x不断右移,判断最右边两位是否都为1,都为1就是有冲突*/
    {
        if((x&3)==3)return 0;
        x>>=1;
    }
    return 1;
}
int main()
{
    int i,j,k;
    while(~scanf("%d",&n))
    {
        for(m=i=0;i<1<<n;++i)
            if(ok(i)) s[m++]=i;  /**枚举所有摆放方案,并判断是否满足,满足就存储在s里*/
        memset(f,0,sizeof(f));   /**赋初值*/
        f[0][0]=1;
        for(i=1;i<=n;++i)        /**枚举每一行*/
            for(j=0;j<m;++j)     /**枚举第i行的状态*/
                for(k=0;k<m;++k)  /**枚举第i-1行的状态*/
                    if((j&k)==0)f[i][j]+=f[i-1][k]; /**如果不冲突就加上*/
        ans=0;
        for(i=0;i<m;++i)ans+=f[n][i]; /**统计答案*/
        printf("%lld\n",ans); /**输出答案*/
    }
    return 0;
}





标签:满足条件,状态,--,摆放,int,棋子,long,dp
From: https://blog.51cto.com/u_16146153/6388989

相关文章

  • 深度理解链式前向星
    我们首先来看一下什么是前向星.前向星是一种特殊的边集数组,我们把边集数组中的每一条边按照起点从小到大排序,如果起点相同就按照终点从小到大排序,并记录下以某个点为起点的所有边在数组中的起始位置和存储长度,那么前向星就构造好了.用len[i]来记录所有以i为起点的边在数组中的......
  • 当鼠标滑过文本框自动选中输入框内容JS代码
    代码:<html><head><title>响应鼠标自动选中文本框内容</title></head><body><inputid="a"type="text"value="请输入搜索词"οnmοuseοver="selectInputContent(this.id)"/><scripttype="text/......
  • 二进制位交换,反转,与统计1的个数
    问题一:给一个整数v,求它的二进制表示中从右往左数第x位和第y位交换后的值(从0开始计数)。 分析:举个例子,如果v的二进制表示为XXXXaXXXXXXbX,我们交换第1位和第8位。我们是这样做的:先把这两位的值都取零后的值保存在一个变量里面,即tmp=XXXX0XXXXXX0X,然后再取ans=0000b000000a0,那么......
  • 求树的重心
    题目:http://poj.org/problem?id=1655题意:给定一棵树,求树的重心的编号以及重心删除后得到的最大子树的节点个数size,如果size相同就选取编号最小的.分析:首先要知道什么是树的重心,树的重心定义为:找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心,删......
  • DP之花店橱窗布置
    题目:https://www.smartoj.com/p/1286分析:花瓶是有序的,花也是有序的,这就保证了有序性,从而满足子解的全局最优,和无后效性.假设dp[i][j]表示前i朵花,放在前j个花瓶里的最优值.则有: 那么经过优化后得到:#include<iostream>#include<string.h>#include<stdio.h>usingnamespac......
  • SBT模版(Size Balanced Tree)
    关于SBT的介绍及学习,请戳这里。 SBT模版:/*************************************************数据结构:SBT(SizeBalancedTree),又称傻逼树;数据域:值域key,左孩子left,右孩子right,保持平衡的size;性质:每棵子树的大小不小于其兄弟的子树大小;插入:插入算法先简单插入节......
  • map()和zip()操作
    对于map()它的原型是:map(function,sequence),就是对序列sequence中每个元素都执行函数function操作。比如之前的a,b,c=map(int,raw_input().split()),意思就是说把输入的a,b,c转化为整数。再比如:a=['1','2','3','4']printmap(list,a)printmap(int,a)第一个map是把列表a中每个......
  • input()与raw_input()
    首先,我们知道input()和raw_input()都是用来获取控制台的输入,当然输入的时候可以加上输入提示信息:    a=raw_input("Pleaseinputa:")    b=input("Pleaseinputb:")那么这两者有什么区别呢?input()支持用户输入数字或者表达式,不支持输入字符串,返回的......
  • 利用JSP交互式打印表格
    问题:在客户端输入要打印表格的行数rows和列数cols,然后经过服务端处理打印rows*cols的表格,打印数据为i*j。html部分:文件名:input.html<html><head><title>Hello</title></head><body><formaction="input.jsp"method="post"><tablebord......
  • Python中的join()函数和split()函数的用法
    题目:CFUltra-FastMathematician 题意:给两个长度相等的0,1字符串,在相同的位置的两个字符不同就输出1,否则输出0.比如:10101000100101就输出:1110001代码:print''.join("10"[i==j]fori,jinzip(raw_input(),raw_input()))join()函数的用法就是把一个list中所有的串按照你定义的分隔......