POJ1185 炮兵部队问题:

在平原上才能放置炮兵,每个炮兵的上下左右2格之内都不能出现别的炮兵

可以考虑在当前行放置炮兵它的右侧和下侧绝对不会出现炮兵即可,左侧和上侧就能省去考虑

明显的状态压缩dp题,但是题目所给的有10列,因为每行都与前两行的状态有关,那么也就是根据当前,上一行,上上行3行状态来修改

dp[i][v][u]的状态方程

因为这里直接3重循环会爆,但是我们很容易发现,可以预处理一些关于行的合法状态,那么状态数就少了很多,接下来考虑的时候就省去了行上的相关影响

 #include <iostream>
#include <cstdio>
#include <cstring>
using namespace std; const int N = <<;
int dp[][][] , state[N];
int can[] , tot[] , cnt;
char str[]; void init_dfs(int k , int u , int v)
{
if(k<){
tot[cnt] = v;
can[cnt++] = u;
return;
}
init_dfs(k- , u|(<<k) , v+);
init_dfs(k- , u , v);
} int main()
{
// freopen("a.in" , "r" , stdin);
int n,m;
while(scanf("%d%d" , &n , &m) != EOF)
{
for(int i= ; i<=n ; i++){
scanf("%s" , str);
state[i] = ;
for(int j= ; j<(int)strlen(str) ; j++){
state[i] <<= ;
if(str[j] == 'P') state[i]+=;
}
// cout<<"state: "<<state[i]<<endl;
}
//找到所有符合的状态,减少状态数
cnt = ;
init_dfs(m- , , );
// cout<<cnt<<endl; if(n==){
int maxn=;
for(int i= ; i<cnt ; i++)
if((state[]&can[i]) == can[i])
maxn = max(maxn , tot[i]);
printf("%d\n" , maxn);
continue;
} memset(dp , , sizeof(dp));
for(int i= ; i<cnt ; i++){
for(int j= ; j<cnt ; j++){
int t1 = state[]&can[i] , t2 = state[]&can[j];
if(t1 == can[i] && t2 == can[j] && !(can[i]&can[j]))
{
// cout<<"test: "<<i<<" "<<j<<" "<<can[i]<<" "<<can[j]<<" tot: "<<tot[i]<<" "<<tot[j]<<endl;
dp[][i][j] = tot[i] + tot[j];
}
}
}
state[] = (<<m)-;
for(int i= ; i<=n ; i++){
for(int u= ; u<cnt ; u++){
if((state[i]&can[u]) < can[u]) continue;
for(int v= ; v<cnt ; v++){
if((state[i-]&can[v]) < can[v]) continue;
if((can[v]&can[u])) continue;
for(int w= ; w<cnt ; w++){
if((state[i-]&can[w]) < can[w]) continue;
if((can[v]&can[w]) || (can[u]&can[w])) continue;
dp[i][v][u] = max(dp[i][v][u] , dp[i-][w][v] + tot[u]);
}
}
}
}
int maxn = ;
for(int i= ; i<cnt ; i++){
for(int j= ; j<cnt ; j++)
maxn = max(maxn , dp[n][i][j]);
}
printf("%d\n" , maxn);
}
return ;
}

POJ 2411 木板拼接问题:

在n*m的方格中,放1*2或者2*1的木板,问有多少摆放的种数

题目会超int,答案输出用long long

这里用dp[i][u]表示到达第 i 行时状态为 u ,且前面行的格子已经全部被木板填充完全,所能达到的方法种数

每次对于当前行的状态只跟上一行有关,dp[i+1][u] += dp[i][v]

通过v可以拼出 u 的情况,我们总是在u,v上放2*1的板,或只在u 上放1*2的板,不能在v上放1*2的板,这样会与原来 v 作为当前行时在其上放1*2的情况重复

且必须保证全部放完后,上一行v 全部填充满(v == (1<<m)-1) ,才更新数据

 #include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define ll long long
ll dp[][]; void dfs(int i , int u , int v , int full , int k , ll val)
{
if(k<){
if(v == full) dp[i][u] += val;
return ;
}
if(k>= && !(u&(<<(k-)))) dfs(i , u|(<<(k-)) , v , full ,k- , val);
if(!(u&(<<k)) && !(v&(<<k))) dfs(i , u|(<<k) , v|(<<k) , full , k- , val);
if(!(v&(<<k))) return ;
dfs(i , u , v , full , k- , val);
} int main()
{
// freopen("a.in" , "r" , stdin);
int n,m;
while(scanf("%d%d" , &n , &m) ,n||m)
{
memset(dp , , sizeof(dp));
dfs( , , (<<m)- , (<<m)- , m- , );
for(int i= ; i<=n ; i++){
for(int j= ; j<(<<m) ; j++){
if(dp[i-][j]) dfs(i , , j , (<<m)- , m- , dp[i-][j]);
}
}
printf("%I64d\n" , dp[n][(<<m)-]);
}
return ;
}

HDU2280 填充问题:

将所给的积木装入平面上,保证最后剩余的格数能够尽可能的少

因为积木最大也就两行,所以每次当前行只受上一行的影响

dp[i][u]记录当前 i 行 状态 为 u 时剩余的格子的最小数目

 #include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = ; int dp[N][] , state[N];
char str[]; int cnt_0(int u)
{
int ans = ;
while(u){
if(u&) ans--;
u>>=;
}
return ans;
} void dfs1(int i , int u , int cnt , int k) //k为当前的长度,从0开始
{
if(k < ){
dp[i][u] = min(dp[i][u] , cnt);
return ;
}
if(k >= && !(u&(<<(k-)))){
int v = u|(<<(k-));
dfs1(i , v , cnt- , k-);
}
dfs1(i,u,cnt,k-);
}
//u为当前行状态,v为上一行状态,cnt为当前行0的数量
void dfs2(int i , int u , int v , int cnt , int k)
{
if(k < ){
dp[i][u] = min(dp[i][u] , cnt);
return ;
}
if(k>=){
if(!(u&(<<(k-)))){
int p = u|(<<(k-));
dfs2(i , p , v , cnt- , k-);
}
if(!(u&(<<(k-))) && !(v&(<<(k-)))){
int p = u|(<<(k-));
int q = v|(<<(k-));
dfs2(i , p , q , cnt- , k-);
}
if(!(u&(<<(k-))) && !(v&(<<k))){
int p = u|(<<(k-));
int q = v|(<<k);
dfs2(i , p , q , cnt- , k-);
}
if(!(v&(<<(k-))) && !(u&(<<(k-)))){
int p = u|(<<(k-));
int q = v|<<(k-);
dfs2(i , p , q , cnt- , k-);
}
if(!(v&(<<(k-))) && !(u&(<<k))){
int p = u|(<<k);
int q = v|(<<(k-));
dfs2(i , p , q , cnt- , k-);
}
}
if(!(u&(<<k)) && !(v&(<<k))){
int p = u|(<<k);
int q = v|(<<k);
dfs2(i , p , q , cnt- , k-);
}
dfs2(i , u , v , cnt , k-);
} int main()
{
// freopen("a.in" , "r" , stdin);
int n , m;
while(scanf("%d%d" , &n , &m) != EOF)
{
for(int i= ; i<=n ; i++){
state[i] = ;
scanf("%s" , str);
for(int j= ; j< ; j++){
int t = str[j]-'';
state[i] = state[i]*+t;
}
} memset(dp , 0x3f , sizeof(dp));
dp[][state[]] = cnt_0(state[]);
dfs1( , state[] , dp[][state[]] , ); for(int i= ; i<=n ; i++){
for(int p= ; p< ; p++){
if(dp[i-][p] <INF){
// cout<<"state : i: "<<i<<" p: "<<p<<" "<<dp[i-1][p]+cnt_0(state[i])<<endl;
dfs2(i , state[i] , p , dp[i-][p]+cnt_0(state[i]) , );
}
}
}
int minn = INF;
for(int i= ; i< ; i++)
minn = min(minn , dp[n][i]);
// cout<<minn<<endl;
printf("%s\n" , minn<=m?"YES":"NO");
}
return ;
}

HDU 2442 方格填充

通过所给的5种形式的木块无覆盖填充n*m的方格,问最多有多少方格被填充

 #include <iostream>
#include <cstdio>
#include <cstring> using namespace std; const int N = <<;
int dp[][N][N]; void dfs(int i , int w , int v , int u , int val , int k)
{
if(k<){
dp[i][v][u] = max(dp[i][v][u] , val);
return;
}
if(k>=){
if(!(w&(<<(k-))) && !(v&(<<(k-))) && !(u&(<<(k-))))
dfs(i , w|(<<(k-)) , v|(<<(k-)) , u|(<<(k-)) , val+ , k-);
if(!(v&(<<(k-))) && !(u&(<<(k-))))
dfs(i , w , v|(<<(k-)) , u|(<<(k-)) , val+ , k-);
if(!(v&(<<(k-))) && !(u&(<<k)))
dfs(i , w , v|(<<(k-)) , u|(<<k) , val+ , k-);
}
if(k>=){
if(!(w&(<<k)) && !(v&(<<(k-))) && !(u&(<<k)))
dfs(i , w|(<<k) , v|(<<(k-)) , u|(<<k) , val+ , k-);
if(!(w&(<<(k-))) && !(v&(<<k)) && !(u&(<<k)))
dfs(i , w|(<<(k-)) , v|(<<k) , u|(<<k) , val+ , k-);
}
dfs(i , w , v , u , val , k-);
} int main()
{
// freopen("a.in" , "r" , stdin);
int n,m;
while(scanf("%d%d" , &n , &m) == )
{
memset(dp , - , sizeof(dp));
dp[][(<<m)-][] = ;
for(int i= ; i<=n ; i++){
for(int w= ; w<(<<m) ; w++){
for(int v= ; v<(<<m) ; v++){
if(dp[i-][w][v]>=) dfs(i , w , v , , dp[i-][w][v] , m-);
}
}
}
int ans = ;
for(int v= ; v<(<<m) ; v++)
for(int u= ; u<(<<m) ; u++)
ans = max(ans , dp[n][v][u]);
printf("%d\n" , ans);
}
return ;
}

状态压缩DP总结的更多相关文章

  1. hoj2662 状态压缩dp

    Pieces Assignment My Tags   (Edit)   Source : zhouguyue   Time limit : 1 sec   Memory limit : 64 M S ...

  2. POJ 3254 Corn Fields(状态压缩DP)

    Corn Fields Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4739   Accepted: 2506 Descr ...

  3. [知识点]状态压缩DP

    // 此博文为迁移而来,写于2015年7月15日,不代表本人现在的观点与看法.原始地址:http://blog.sina.com.cn/s/blog_6022c4720102w6jf.html 1.前 ...

  4. HDU-4529 郑厂长系列故事——N骑士问题 状态压缩DP

    题意:给定一个合法的八皇后棋盘,现在给定1-10个骑士,问这些骑士不能够相互攻击的拜访方式有多少种. 分析:一开始想着搜索写,发现该题和八皇后不同,八皇后每一行只能够摆放一个棋子,因此搜索收敛的很快, ...

  5. DP大作战—状态压缩dp

    题目描述 阿姆斯特朗回旋加速式阿姆斯特朗炮是一种非常厉害的武器,这种武器可以毁灭自身同行同列两个单位范围内的所有其他单位(其实就是十字型),听起来比红警里面的法国巨炮可是厉害多了.现在,零崎要在地图上 ...

  6. 状态压缩dp问题

    问题:Ignatius has just come back school from the 30th ACM/ICPC. Now he has a lot of homework to do. Ev ...

  7. BZOJ-1226 学校食堂Dining 状态压缩DP

    1226: [SDOI2009]学校食堂Dining Time Limit: 10 Sec Memory Limit: 259 MB Submit: 588 Solved: 360 [Submit][ ...

  8. Marriage Ceremonies(状态压缩dp)

     Marriage Ceremonies Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu ...

  9. HDU 1074 (状态压缩DP)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1074 题目大意:有N个作业(N<=15),每个作业需耗时,有一个截止期限.超期多少天就要扣多少 ...

  10. HDU 4511 (AC自动机+状态压缩DP)

    题目链接:  http://acm.hdu.edu.cn/showproblem.php?pid=4511 题目大意:从1走到N,中间可以选择性经过某些点,比如1->N,或1->2-> ...

随机推荐

  1. 题解报告:hdu 2544 最短路

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2544 Problem Description 在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t ...

  2. Android最简单的实例 :环境搭建及HelloWorld

    Android开发之旅:环境搭建及HelloWorld 2010-04-12 00:45 by 吴秦, 883961 阅读, 140 评论, 收藏,  编辑 ——工欲善其事必先利其器 引言 本系列适合 ...

  3. C#控件置于底层或顶层

    btn.BringToFront();//置于顶层 btn.SendToBack();//置于底层

  4. js 将XML字符串解析成XML文档 --- attribute construct error--- 空白字符与空格问题

    最近在做xml在线编辑器,遇到一个字符串解析成xml文档的问题,记录一下. 原始xml内容读取自xml文档 <label class="test" id="labe ...

  5. spark集群启动步骤及web ui查看

    集群启动步骤:先启动HDFS系统,在启动spark集群,最后提交jar到spark集群执行. 1.hadoop启动cd /home/***/hadoop-2.7.4/sbinstart-all.sh ...

  6. nginx访问php程序相关配置

    server { listen *:80; charset utf-8; server_name roujiaxiaomowang.wanghaokun.com mowang.crucco.com; ...

  7. Linq详细介绍

    声明----文档转载自:http://www.cnblogs.com/liulun/archive/2013/02/26/2909985.html 在说LINQ之前必须先说说几个重要的C#语言特性 一 ...

  8. iTOP-6818开发板-Android4.4系统下RFID射频模块测试例程

    平台:迅为iTOP-6818开发板 系统:Android4.4版本 例程:RFID射频模块测试例程 rc522 驱动在 Android 系统的内核是默认集成的,用户可以在开发板上使用命令“ls /de ...

  9. comm - 逐行比较两个已排序的文件

    总览 (SYNOPSIS) ../src/comm [OPTION]... LEFT_FILE RIGHT_FILE 描述 (DESCRIPTION) 逐行比较 已排序的 文件 LEFT_FILE 和 ...

  10. 移动端1px线适配问题-------适配各种编译CSS工具 stylus sass styled-componet实现方法

    其实在stylus与sass中实现移动端1像素线各个手机设备的适配问题的原理是一样的, 首先我还是先介绍一下原理和所依赖的方法 原理:其实他们都是通过css3的媒体查询来实现的 步骤思路: 1.给目标 ...