状态压缩dp入门

poj1321 http://poj.org/problem?id=1321

我们可以把棋盘的每一行看做是一个状态,如果某一列放置了棋子,那么就标记为1,否则就标记为0.然后把它看成是一个二进制数,然后转为10进制数,就可以当做数组下标然后进行状态转移了

设dp[i][s] 为处理到第i行时,状态为s的方法数

那么我们枚举第i-1行的所有状态s

dp[i][s] += dp[i-1][s]; //表示第i行不放置棋子的方法数

dp[i][s|(1<<j)] += dp[i-1][s] //表示第i行第j列放置棋子的方法数   (前提是 chess[i][j]==‘#‘ && 状态s第j列没有放过棋子)

 1 #include <stdio.h>
 2 #include <string.h>
 3 char chess[9][9];int dp[11][1<<8];
 4 int n,k;
 5 int main()
 6 {
 7     int i,j,s,ss;
 8     while(scanf("%d%d",&n,&k)!=EOF)
 9     {
10         int ans = 0;
11         if(n==-1) return 0;
12         memset(dp,0,sizeof(dp));
13         for(i=1; i<=n; ++i)
14         {
15             scanf("%s",chess[i]);
16         }
17         dp[0][0] = 1;
18         for(i=1; i<=n; ++i)
19             for(s=0; s<(1<<n); ++s)
20             {
21
22                 for(j=0; j<n; ++j)
23                     if(chess[i][j]==‘#‘&&((1<<j)&s)==0)
24                         dp[i][s|1<<j] += dp[i-1][s];//表示第i行第j列放置棋子的方法数
25                 dp[i][s] += dp[i-1][s]; //表示第i行不放置棋子的方法数
26             }
27         ///for(j=1; j<=n; ++j)
28         for(s=0; s<(1<<n); ++s)
29         {
30             i = s;
31             int cnt = 0 ;
32             for(;i;i-= i&-i)//统计状态s有多少个1,表示放了多少个棋子
33                 cnt ++;
34             if(cnt==k)
35                 ans+= dp[n][s];
36         }
37         printf("%d\n",ans);
38     }
39     return 0;
40 }
时间: 2024-09-29 16:59:17

状态压缩dp入门的相关文章

Hdu-1565 方格取数(1) (状态压缩dp入门题

方格取数(1) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4702    Accepted Submission(s): 1782 Problem Description 给你一个n*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出

hoj 2662 Pieces Assignment 状态压缩dp入门

//hoj 2662 Pieces Assignment //有一个n*m的棋盘(n.m≤80,n*m≤80)要在棋盘上放k(k≤20)个棋子,使得任意两 //个棋子不相邻(每个棋子最多和周围4个棋子相邻).求合法的方案总数. // //算是另一个状态压缩dp入门吧 //dp[i][S][j]表示第i行的棋子状态是S(整数的二进制形式,比如5为 // ...101,省略号表示前导0,那一位上是1就表示哪一列上放了棋子,5表示第一列 //第三列放了棋子.)时已经放了j颗棋子,则转移方程为: //d

状态压缩dp入门 (poj3254 Corn Fields)

题目链接:http://poj.org/problem?id=3254 题意:给出一个n行m列的草地,1表示肥沃,0表示贫瘠,现在要把一些牛放在肥沃的草地上,但是要求所有牛不能相邻,问你有多少种放法. 分析:假如我们知道第 i-1 行的所有的可以放的情况,那么对于第 i 行的可以放的一种情况,我们只要判断它和 i - 1 行的所有情况的能不能满足题目的所有牛不相邻,如果有种中满足,那么对于 i 行的这一中情况有 x 中放法. 前面分析可知满足子状态,我们我们确定可以用dp来解决. 但是我们又发现

动态规划之状态压缩dp入门

状态压缩动态规划(简称状压dp)是另一类非常典型的动态规划,通常使用在NP问题的小规模求解中,虽然是指数级别的复杂度,但速度比搜索快,其思想非常值得借鉴. 为了更好的理解状压dp,首先介绍位运算相关的知识. 1.'&'符号,x&y,会将两个十进制数在二进制下进行与运算,然后返回其十进制下的值.例如3(11)&2(10)=2(10). 2.'|'符号,x|y,会将两个十进制数在二进制下进行或运算,然后返回其十进制下的值.例如3(11)|2(10)=3(11). 3.'^'符号,x^y

状态压缩dp入门 第一题 POJ 3254 Corn Fields

Corn Fields Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 6460   Accepted: 3436 Description Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ≤ 12) square parcels. He wants to grow some yumm

Poj 1185 炮兵阵地(状态压缩dp 入门题)

炮兵阵地 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 17272   Accepted: 6593 Description 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P"表示),如下图.在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队):一支炮兵部队在地图上的攻击

poj 3250 状态压缩dp入门

Corn Fields Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 7798   Accepted: 4159 Description Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ≤ 12) square parcels. He wants to grow some yumm

状态压缩dp 入门

1.有一张n*m (n<=m)的棋盘,在上面放n个中国象棋里的车,使得任意两个车不能相互攻击,总共有多少种不同的方案. 2.有一张n*m (n<=m)的棋盘,其中有些格子里面不能放,在上面放n个中国象棋里的车,使得任意两个车不能相互攻击,总共有多少种不同的方案. 3.有一张n*m (n<=m)的棋盘,最多可以在上面放多少中国象棋里的马,使得任意两个马不能相互攻击.

POJ--3311--Hie with the Pie(暴力枚举+floyd)/(状态压缩DP+floyd)

简介 状态压缩入门,先说用暴力枚举的方法做的,再说状态压缩DP,对于刚开始学习状态压缩的同学,两者相互比较学习,可以明显看出两者区别,有利于对状态压缩DP的理解,提前说下,两者耗时是 157Ms和 0Ms . 题意 一披萨店员送披萨,从披萨店开始送给N个客户会给你一个(N+1)*(N+1)的矩阵,对于矩阵 g[i][j] 表示 i 处到 j 处所耗费的时间,0 代表披萨店,每条路径可以重复走. 问:店员从披萨店开始送完所有的披萨再返回店中的最短耗时.注意,出店就拿有 N 个披萨,不必重复返回店里