炮兵阵地

Language:Default
炮兵阵地
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 34008 Accepted: 13083

Description

司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队。一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P"表示),如下图。在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队);一支炮兵部队在地图上的攻击范围如图中黑色区域所示:



如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。图上其它白色网格均攻击不到。从图上可见炮兵的攻击范围不受地形的影响。

现在,将军们规划如何部署炮兵部队,在防止误伤的前提下(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围内),在整个地图区域内最多能够摆放多少我军的炮兵部队。

Input

第一行包含两个由空格分割开的正整数,分别表示N和M;

接下来的N行,每一行含有连续的M个字符('P'或者'H'),中间没有空格。按顺序表示地图中每一行的数据。N <= 100;M <= 10。

Output

仅一行,包含一个整数K,表示最多能摆放的炮兵部队的数量。

Sample Input

5 4
PHPP
PPHH
PPPP
PHPP
PHHP

Sample Output

6

Source

分析

由于会影响两行,所以需要在行数以外增加两维状态。

预处理出单行的合法状态,大概在60左右,然后枚举转移即可。

时间复杂度\(o(n 60^3)\),由于地形的因数,状态量又会减少,上界很松。

#include<iostream>
#include<cstring>
#define rg register
#define il inline
#define co const
template<class T>il T read(){
rg T data=0,w=1;rg char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') w=-1;ch=getchar();}
while(isdigit(ch)) data=data*10+ch-'0',ch=getchar();
return data*w;
}
template<class T>il T read(rg T&x) {return x=read<T>();}
typedef long long ll;
using std::max; int dp[101][77][77];
int sg[101];
int n,m,idx,s[77],cnt0[77];
int get_one(int x){
int cnt=0;
while(x) x&=x-1,++cnt;
return cnt;
}
bool ok(int x){
return x&x<<1||x&x<<2?0:1;
}
void init(){
for(int i=0;i<1<<m;++i)if(ok(i)){
s[idx]=i,cnt0[idx++]=get_one(i);
}
}
bool valid(int i,int x){
return sg[i]&x?0:1;
}
int solve(){
int ans=0;
memset(dp,-1,sizeof dp);
dp[0][0][0]=0;
for(int i=0;i<idx;++i)if(valid(1,s[i])){
dp[1][i][0]=cnt0[i];
ans=max(ans,dp[1][i][0]);
}
for(int i=2;i<=n;++i)
for(int j=0;j<idx;++j)if(valid(i,s[j]))
for(int k=0;k<idx;++k)if(valid(i-1,s[k])&&(s[j]&s[k])==0){
int last=0;
for(int l=0;l<idx;++l)if(dp[i-1][k][l]!=-1&&(s[l]&s[j])==0)
last=max(last,dp[i-1][k][l]);
dp[i][j][k]=max(dp[i][j][k],last+cnt0[j]);
if(i==n) ans=max(ans,dp[i][j][k]);
}
return ans;
}
int main(){
// freopen(".in","r",stdin),freopen(".out","w",stdout);
read(n),read(m);
for(int i=1;i<=n;++i){
static char s[11];
scanf("%s",s);
for(int j=0;j<m;++j)
if(s[j]=='H') sg[i]|=1<<j;
}
init();
printf("%d\n",solve());
return 0;
}

Mondriaan's Dream

Language:Default
Mondriaan's Dream
Time Limit: 3000MS Memory Limit: 65536K
Total Submissions: 21909 Accepted: 12282

Description

Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his 'toilet series' (where he had to use his toilet paper to draw on, for all of his paper was filled with squares and rectangles), he dreamt of filling a large rectangle with small rectangles of width 2 and height 1 in varying ways.



Expert as he was in this material, he saw at a glance that he'll need a computer to calculate the number of ways to fill the large rectangle whose dimensions were integer values, as well. Help him, so that his dream won't turn into a nightmare!

Input

The input contains several test cases. Each test case is made up of two integer numbers: the height h and the width w of the large rectangle. Input is terminated by h=w=0. Otherwise, 1<=h,w<=11.

Output

For each test case, output the number of different ways the given rectangle can be filled with small rectangles of size 2 times 1. Assume the given large rectangle is oriented, i.e. count symmetrical tilings multiple times.

Sample Input

1 2
1 3
1 4
2 2
2 3
2 4
2 11
4 11
0 0

Sample Output

1
0
1
2
3
5
144
51205

Source

分析

网上一些题解都是什么鬼,轮廓线、插头DP都冒出来了。

用\(F[i,j]\)表示前\(i\)行,第\(i\)行的放置状态为\(j\)的方案数,把特殊的\(1\times 2\)矩形的上半部分的状态定为1。

这样\(j\)能转移到\(k\),当且仅当

  1. \(j\&k=0\),显然的。
  2. \(j|k\)的每一段连续的0的数量必须有偶数个,这体现了\(2\times 1\)矩形的要求。

预处理出那些状态转移合法,大力转移即可。

时间复杂度\(O(n 2^{2m})\)

#include<iostream>
#define rg register
#define il inline
#define co const
template<class T>il T read(){
rg T data=0,w=1;rg char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') w=-1;ch=getchar();}
while(isdigit(ch)) data=data*10+ch-'0',ch=getchar();
return data*w;
}
template<class T>il T read(rg T&x) {return x=read<T>();}
typedef long long ll; int n,m;
ll f[12][1<<11];
bool in_s[1<<11];
int main(){
// freopen(".in","r",stdin),freopen(".out","w",stdout);
while(read(n)|read(m)){
for(int i=0;i<1<<m;++i){
bool cnt=0,has_odd=0;
for(int j=0;j<m;++j){
if(i>>j&1) has_odd|=cnt,cnt=0;
else cnt^=1;
}
in_s[i]=has_odd|cnt?0:1;
}
f[0][0]=1;
for(int i=1;i<=n;++i)
for(int j=0;j<1<<m;++j){
f[i][j]=0;
for(int k=0;k<1<<m;++k)
if((j&k)==0&&in_s[j|k])
f[i][j]+=f[i-1][k];
}
printf("%lld\n",f[n][0]);
}
return 0;
}

POJ1185 炮兵阵地 和 POJ2411 Mondriaan's Dream的更多相关文章

  1. [poj1185]炮兵阵地_状压dp

    炮兵阵地 poj-1185 题目大意:给出n列m行,在其中添加炮兵,问最多能加的炮兵数. 注释:n<=100,m<=10.然后只能在平原的地方建立炮兵. 想法:第2到状压dp,++.这题显 ...

  2. POJ1185炮兵阵地【动态规划】

    炮兵阵地 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 26892   Accepted: 10396 Descriptio ...

  3. POJ2411 Mondriaan's Dream(状态压缩)

    Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 15295   Accepted: 882 ...

  4. poj1185 炮兵阵地【状压DP】

    炮兵阵地 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 32802   Accepted: 12650 Descriptio ...

  5. poj2411 Mondriaan's Dream【状压DP】

    Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 20822   Accepted: 117 ...

  6. POJ1185 炮兵阵地 —— 状压DP

    题目链接:http://poj.org/problem?id=1185 炮兵阵地 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions ...

  7. [Poj2411]Mondriaan's Dream(状压dp)(插头dp)

    Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 18096   Accepted: 103 ...

  8. poj2411 Mondriaan's Dream (轮廓线dp、状压dp)

    Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 17203   Accepted: 991 ...

  9. [poj2411] Mondriaan's Dream (状压DP)

    状压DP Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One nigh ...

随机推荐

  1. java后台面试之计算机网络问题集锦

    1.http和https的区别 2.对称加密和非对称加密 3.三次握手与四次挥手的流程 4.为什么TCP需要三次握手?两次不可以吗?为什么 5.为什么TCP挥手需要四次?三次不行吗? 6.TCP协议如 ...

  2. LC 297 Serialize and Deserialize Binary Tree

    问题: Serialize and Deserialize Binary Tree 描述: Serialization is the process of converting a data stru ...

  3. Hbuilder环境下配置php

    XAMPP的安装 https://blog.csdn.net/qing666888/article/details/81914389 安装并配置好Xampp后,在Hbuilder中下载php插件,工具 ...

  4. SQL——INSERT INTO(增)

    一.INSERT INTO语句的基本用法 INSERT INTO 语句用于往表中插入新记录. student表: INSERT INTO语句有2种语法格式: 1.不指定列名,直接插入记录. 语法格式如 ...

  5. SQL高级教程

    一.top子句 top子句用于规定要返回的记录的数目 并非所有数据库系统都支持top子句 # sqlserver SELECT TOP number|percent column_name(s) FR ...

  6. (转)FFmpeg架构之I/O模块分析

    注意:这篇转载的文章比较早,写得很清晰,但是新版的ffmpeg的很多数据结构的名字已经改了.因此只能作参考.(例如ByteIOContext已经改名为AVIOContext) 1概述 ffmpeg项目 ...

  7. Eclipse RCP难点:给Command传递参数(Object)

    这个问题网络上没有答案,国外网站上也没有,本人研究了一天,终于搞明白如何实现,实际上是Eclipse RCP的ICommandService本身就已经提供的方法,只是网络上教的都是使用IHandler ...

  8. Markdown笔记(git提交带有emoji的commit描述)

    用法:> git commit -m ' :tada: initial ' emoji来源:> ![gitmoji](https://gitmoji.carloscuesta.me/sta ...

  9. Python中闭包的原理

    定义: 如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure). 简单闭包的例子: 下面是一个使用闭包简单的例子,模拟一个计数器,通过将 ...

  10. sql 防注入(更新问题)

    一下这条语句虽然不会是数据表中的数据发生变化,但是会对数据库主从造成影响 update `article` where `article_id` = '40&n974742=v995656' ...