状压DP学习

  

  1. POJ3254 Corn Fields

  设dp[i][j] 表示第i行状态为j的合法方案的个数

  dp[i][j] = dp[i][j] + dp[i-1][k] 当然状态方程很好写,重点在与怎么判断是否是合法的方案,鉴于这题比较简单就不细说

  (1)当前行内,不能有相邻的两个1

  (2)当前行与上一行是否冲突

  (3)当前状态是否满足题目给出的图

  

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <string>
 5 #include <iostream>
 6 #include <algorithm>
 7 #include <cmath>
 8 #include <vector>
 9 #include <map>
10 using namespace std;
11 const int maxn = 13;
12 const int maxv = 50005;
13 const int INF = 0x3f3f3f3f;
14 const int mod = 1e8;
15 typedef __int64 LL;
16 int dp[maxn][1<<maxn];
17 int a[maxn];
18 bool isok(int j)
19 {
20     return !(j & (j<<1));
21 }
22 int main()
23 {
24 //    freopen("in.txt","r",stdin);
25 //    freopen("out.txt","w",stdout);
26     int n,m;
27     while(cin>>n>>m)
28     {
29         memset(dp,0,sizeof(dp));
30         memset(a,0,sizeof(a));
31         for(int i = 1;i<=n;++i)
32             for(int j = 0;j<m;++j)
33             {
34                 int t;
35                 scanf("%d",&t);
36                 if(t)a[i] = a[i]|(1<<j);
37             }
38         dp[0][0] = 1;
39         m = 1<<m;
40         for(int i = 1;i<=n;++i)
41             for(int j = 0;j<m;++j)if((a[i]|j)==a[i] && isok(j))
42                 for(int k = 0;k<m;++k)if(!(j & k))
43                     dp[i][j] = (dp[i][j]+dp[i-1][k])%mod;
44         int ans = 0;
45         for(int i = 0;i<m;++i)
46             ans = (ans+dp[n][i])%mod;
47         cout<<ans<<endl;
48     }
49
50     return 0;
51 }
时间: 2024-10-11 17:43:29

状压DP学习的相关文章

BZOJ 3446: [Usaco2014 Feb]Cow Decathlon( 状压dp )

水状压dp. dp(x, s) = max{ dp( x - 1, s - {h} ) } + 奖励(假如拿到的) (h∈s). 时间复杂度O(n * 2^n) ---------------------------------------------------------------------------------- #include<bits/stdc++.h> #define rep(i, n) for(int i = 0; i < n; ++i) #define clr(x

Codeforces Gym 100676G Training Camp 状压dp

http://codeforces.com/gym/100676 题目大意是告诉你要修n门课,每门课有一个权值w[i], 在第k天修该课程讲获得k*w[i]的学习点数,给出了课程与先修课程的关系,要修该课程必须修完先修课程.问最多能学到多少点数. 非常简单的一道状压dp(一开始我还误导队友写成两维的去了 T^T); dp[s] : s 的二进制存放的是已经选择的课程,在该状态下的能获得的最大的点数. 这时如果再学一门课程k,将转移到状态ss (s | (1 << k) ) ,能否转移需要判断合

poj1185:炮兵阵地(状压dp)

也算是比较基础的状压dp了,跟做过的第二道比较又稍微复杂了一点 需要记录之前两行的状态.. 统计结果也稍有不同 另外还学习了一个得到一个整数二进制位 1 的个数的位运算方法 详见代码: #include <iostream> #include <stdio.h> #include<string.h> #include<algorithm> #include<string> #include<ctype.h> using namespa

状压DP UVA 10817 Headmaster&#39;s Headache

题目传送门 1 /* 2 题意:学校有在任的老师和应聘的老师,选择一些应聘老师,使得每门科目至少两个老师教,问最少花费多少 3 状压DP:一看到数据那么小,肯定是状压了.这个状态不好想,dp[s1][s2]表示s1二进制表示下至少有1位老师的科目集合 4 s2表示至少有2位老师的科目集合所花费的最小金额,状态转移方程(01):dp[t1][t2]=min(dp[t1][t2],dp[j][k]+c[i]); 5 j,k为当前两个集合,t1,t2为转移后的集合,另外求t1,t2用到了& |位运算

poj 2441 Arrange the Bulls(状压DP入门)

Arrange the Bulls Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 3509   Accepted: 1344 Description Farmer Johnson's Bulls love playing basketball very much. But none of them would like to play basketball with the other bulls because the

CF 1042B. Vitamins(状压dp)

以此题开始进入学习状压dp~ 题目大意 输入每瓶维生素的价格以及所含维生素元素,若能买到包含abc三种维生素,输出所需最小价钱,否则输出-1. 题解 状压dp,每种维生素对应一位,求出数值7(即二进制111)所对应的价格 代码 1 #include <iostream> 2 #include <string> 3 #include <algorithm> 4 using namespace std; 5 6 int main() 7 { 8 int dp[8], tmp

ZOJ3305Get Sauce 状压DP,

状压DP的题目留个纪念,首先题意一开始读错了,搞了好久,然后弄好了,觉得DFS可以,最后超时,修改了很久还是超时,没办法看了一下n的范围,然后觉得状压可以,但是没有直接推出来,就记忆化搜索了一下,可是一直错,莫名奇妙,然后没办法看了一下题解,发现了下面这个比较好的方法,然后按照这个方程去推,然后敲,也是WA了好多把,写的太搓了,没人家的清楚明了,唉~也算是给自己留个纪念,状压一直做的都不太好~唉~还好理解了, 参考了  http://blog.csdn.net/nash142857/articl

poj 2411 Mondriaan&#39;s Dream(状压DP)

Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 12232   Accepted: 7142 Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his 'toilet series

(状压dp)uva 10817 Headmaster&#39;s Headache

题目地址 1 #include <bits/stdc++.h> 2 typedef long long ll; 3 using namespace std; 4 const int MAX=1e5+5; 5 const int INF=1e9; 6 int s,m,n; 7 int cost[125]; 8 //char sta[MAX]; 9 string sta; 10 int able[125]; 11 int dp[125][1<<8][1<<8]; 12 in