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颗棋子,则转移方程为:
//dp[i][S][j] = sigma(dp[i-1][V][j-get(V)])
//dp[i-1][V][j-get(V)]表示第i-1行的棋子状态是V时已经放了j-get(V)颗棋子
//get(V)表示V状态下的放了棋子的个数
//在求get(V)时,本身就要判断V是否合法,所以用到了一个S,有些巧妙
//最后sigma(dp[n][S][k])就是我们所求的答案。

//这题在刚开始的时候完全不会处理,只知道有四重循环,对细节的处理不到位
//导致wa了无数发,哎,继续练吧。。。

#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <cfloat>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#define ceil(a,b) (((a)+(b)-1)/(b))
#define endl '\n'
#define gcd __gcd
#define highBit(x) (1ULL<<(63-__builtin_clzll(x)))
#define popCount __builtin_popcountll
typedef long long ll;
using namespace std;
const int MOD = 1000000007;
const long double PI = acos(-1.L);

template<class T> inline T lcm(const T& a, const T& b) { return a/gcd(a, b)*b; }
template<class T> inline T lowBit(const T& x) { return x&-x; }
template<class T> inline T maximize(T& a, const T& b) { return a=a<b?b:a; }
template<class T> inline T minimize(T& a, const T& b) { return a=a<b?a:b; }

ll dp[85][1<<9][30];
int n,m,k;

int get(int x){
	int i=0,s=0;
	while(x){
		if (s&&(x&1))	return -1;
		if (s = (x&1))
			i++;
		x>>=1;
		//i++;
	}
	return i;
}

void solve(){
	memset(dp,0,sizeof(dp));
	dp[0][0][0] = 1;
	for (int i=1;i<=n;i++){
		for (int j=0;j<=k;j++){
			for (int S=0;S<(1<<m);S++){
				int t = get(S);
				if (t==-1||t>j)	continue;
				for (int V=0;V<(1<<m);V++){
					if (get(V)==-1||(V&S))	continue;
					dp[i][S][j] +=dp[i-1][V][j-t];
				}
			}
		}
	}
	ll ans = 0;
	for (int i=0;i<(1<<m);i++)
		ans += dp[n][i][k];
	printf("%lld\n",ans);
}

int main() {
    freopen("G:\\Code\\1.txt","r",stdin);
	while(scanf("%d%d%d",&n,&m,&k)!=EOF){
		if (n<m)
			swap(n,m);
		solve();

	}
	return 0;
}

时间: 2024-10-29 02:45:37

hoj 2662 Pieces Assignment 状态压缩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个格子不能相邻,并且取出

状态压缩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"表示),如下图.在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队):一支炮兵部队在地图上的攻击

状态压缩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] //表示

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)的棋盘,最多可以在上面放多少中国象棋里的马,使得任意两个马不能相互攻击.

hoj 2662 状态压缩dp

题意: 给定mxn的棋盘,要往其中放d枚棋子,其中,一枚棋子的上下左右四个位置不能再放棋子.求所有合法的放置状态 ( 0<m,n<=80 , mxn<=80 ) 棋盘位置可多达80,爆搜目测超时,我用的状态压缩dp. 棋盘中的一个格子,放棋用1,不放用0 压缩其中一维,每个状态数用一个二进制数表示. 每个状态都是棋盘一行的放置方法 假设,m >= n , 这个递推棋盘就有 m行 ,每行至多有 2^n-1个状态数.其实,没有这么多!按照题意,每个1的上下左右不能有1.对于一行,只知左