正确的打炮方式(大雾)(点我查看)

  2015-08-21

  问题是中文的,大家可以进去看看。

  先说一个坑,这个问题我交了很多次,都没过,反正是WA到我烦了,都不知道哪里错了!!!怎么会有错,然后翻了一下别人的代码,立马懂了

  原因就是这题是因为他输入是字符,我一般清字符就直接用一个fflush(stdin)就完事了,上次石子游戏就坑了我一次,所以我这次没用fflush了,因为fflush会清掉整个缓冲区,而在线提交的原理就是把一大堆测试数据放缓冲区一个一个读的,真是太坑了,我以为在线编译器会直接忽略\n的,然而显然它没有

                      

  OK我们回到这一题上来,这一题和我上一次写过的稻田养牛(点我查看)比较像,那么区别在哪里呢?嗯,区别就在这一题要存两个位置,因为炮兵可以打到两个区域,而且左右的判断规则也不同,并且这一题是要算的最大数量(而不是组合数)。嗯。

  那么我们现在要想的问题就是怎么保存两个位置就好了,并且这两行的信息必须集中到一起(不然怎么叫状态压缩呢),所以我们立马就想到了用一个二维数组。同时,因为这题是算的最大数量,我们可以规定一个“不合法位置”为-1,来简化判断条件(这样就不用再和图的上一行和上上一行的P,H位置进行比较了,比较方便)。

  那么,最后我们得出的二维数组将会蕴含下列信息:

     1.至上一行为止的每一个状态所对应的最大炮兵数

     2.并且上一行与上上一行肯定满足所有的对应限制(不然肯定会显示-1非合法位置)

    所以,我们现在只用本行和上上一行的炮兵满足不在一列的要求就可以了,也是蛮方便的。

    状态转移方程:Now_State[j][k]=max(Now[j][k],Prev[k][h]+State_men[j]);很简单

这个题的确比稻田那个要难一点,主要是两行情况要注意一下,而且还要算炮兵数(这个有一个技巧,在注释写了)

#include <stdio.h>
#include <stdlib.h>
#include <string.h> void Search(const int, const int, int *const);
void Inivilize_Valid_State(const int, int *const, int **, int **);
void ReMark(int **,const int);
int **Inivilize_Sum_State(const int);
static int If_Valid(const int, const int);
static int Cal_Men_Of_State(const int);
static int max_(const int, const int); int main(void)
{
int M, N, i, j, *line = NULL;
char tmp; while (scanf("%d%d", &N, &M) != EOF)
{
//H的比特位就是1,P就是1
line = (int *)malloc(sizeof(int)*N);
for (i = ; i < N; i++)
{
getchar();
line[i]= ;
for (j = ; j < M; j++)
{
tmp = getchar();
if (tmp == 'H')
line[i] |= ( << (M - j - ));
}
}
Search(N, M, line);
free(line);
}
return ;;
} static int If_Valid(const int state1, const int state2)
{
/*Name: If_Valid
*Function: 判断相邻两行之间是否违反了炮兵不能在同一列的规定(或者隔行)
判断是否违反了H位置不能放炮兵的规定
*Return: 合法返回1,不合法返回0
*/
if (state1&state2)
return ;
return ;
} void Inivilize_Valid_State(const int n, int *const valid_state_sum, int **Valid_State, int **State_men)
{
/*Name: Inilivilize:
*Function: 遍历每一行可能的组合方式,找到可以放炮兵的那些合法位置,存起来
*return: 无
*/
*valid_state_sum = ;
*Valid_State = (int *)malloc(sizeof(int)*n);
*State_men = (int *)malloc(sizeof(int)*n);
int i;
for (i = ; i < n; i++)
{
if ((!(i&(i << ))) && (!(i&(i << )))){
//这个表示当一个位置是1时,其左右的两个位置都必须是空位置才行
//比如100100这个就是合法位置,而110100这些就不行
(*Valid_State)[(*valid_state_sum)] = i;
(*State_men)[(*valid_state_sum)++] = Cal_Men_Of_State(i);
}
}
} static int Cal_Men_Of_State(const int i)
{
/*Name: Cal_Men_Of_State
*Function: 计算每一个合法位置的1的个数(也就是放炮兵的个数)
*返回值: 这个合法位置的炮兵的个数
*/
int k = i, sum_men = ;
while (k)
{
//这个位运算的意思是去掉所有的1,然后统计去掉的1的数量
//比如1010,-1以后变成1001,然后再和1010按位与,就得出了1000,去了一个1
//1000再-1变0111,按位与变0000,又去掉一个1,然后k=0,退出循环
sum_men++;
k &= (k - );
}
return sum_men;
} inline int **Inivilize_Sum_State(const int valid_state_sum)
{
/*Name: Inivilize_Sum_State
*Function: 初始化Now Prev位置
*Return: 返回对应地址
*/
int **tmp = (int **)malloc(sizeof(int)*valid_state_sum);
int i;
for (i = ; i < valid_state_sum; i++)
{
tmp[i] = (int *)malloc(sizeof(int)*valid_state_sum);
memset(tmp[i], (int)-, sizeof(int)*valid_state_sum);
}
return tmp;
} void ReMark(int **tmp, const int valid_state_sum)
{
/*Name: ReMark
*Function: 初始化Now位置
*Return: 返回对应地址
*/
int i;
for (i = ; i < valid_state_sum; i++)
memset(tmp[i], (int)-, sizeof(int)*valid_state_sum);
} static int max_(const int a, const int b)
{
return a > b ? a : b;
} void Search(const int line, const int col, int *const Gragh)
{
/*Name: Search
*Function: 得出最大炮兵数量
*Return: 无
*/
int valid_state_sum, i, j, k, h, max;
int *State_men = NULL, *Valid_State = NULL;
Inivilize_Valid_State(( << col), &valid_state_sum, &Valid_State, &State_men);
//注意(1<<col)是表示有多少列就有2^col个比特位的组合哦 int **Now_State = Inivilize_Sum_State(valid_state_sum);
int **Prev = Inivilize_Sum_State(valid_state_sum);
int **ec = NULL; for (i = ; i < valid_state_sum; i++)
{
if (If_Valid(Gragh[], Valid_State[i]))
Now_State[i][] = State_men[i];
}
ec = Prev; Prev = Now_State; Now_State = ec;
ReMark(Now_State, valid_state_sum); for (i = ; i < line; i++)
{
for (j = ; j < valid_state_sum; j++)
{
if (If_Valid(Gragh[i], Valid_State[j]))
{
for (k = ; k < valid_state_sum; k++)
{
if (!(Valid_State[k] & Valid_State[j]))
{
for (h = ; h < valid_state_sum; h++)
{
if (!(Valid_State[h] & Valid_State[j])
&& Prev[k][h] != -)
Now_State[j][k] = max_(Now_State[j][k], Prev[k][h] + State_men[j]);
}
}
}
}
}
ec = Prev; Prev = Now_State; Now_State = ec;
ReMark(Now_State, valid_state_sum);
}
for (i = , max = ; i < valid_state_sum; i++)
for (j = ; j < valid_state_sum; j++)
max = max_(Prev[i][j], max); printf("%d\n", max);
for (i = ; i < valid_state_sum; i++)
free(Now_State[i]);
for (j = ; j < valid_state_sum; j++)
free(Prev[j]);
free(Now_State); free(Prev);
}

最后说一下,如果这道题要你算组合数,那么就不能标记-1为不合理位置了,那必须上一行和上上一行要和PH位置进行两次对比,然后还要上一行和上上一行不产生冲突才行

另外这题WA真是太恶心了,搞得我最近几天都不想写代码了,真是醉

  

DP:炮兵阵地问题(POJ 1185)的更多相关文章

  1. 炮兵阵地(POJ 1185状压dp)

    题意:n*m地图'H'能放'p'不能放,布兵的方格上下左右不能布兵,给你地图求最大布兵数 分析:关系到前两行,所以dp[i][j][k]第i行状态为j,i-1行状态为k时的最大布兵数, 先求出所有可行 ...

  2. POJ 1185 状态压缩DP 炮兵阵地

    题目直达车:   POJ 1185 炮兵阵地 分析: 列( <=10 )的数据比较小, 一般会想到状压DP. Ⅰ.如果一行10全个‘P’,满足题意的状态不超过60种(可手动枚举). Ⅱ.用DFS ...

  3. [状压DP]炮兵阵地

    炮 兵 阵 地 炮兵阵地 炮兵阵地 题目描述 司令部的将军们打算在 N ∗ M N*M N∗M的网格地图上部署他们的炮兵部队.一个 N ∗ M N*M N∗M的地图由 N N N行 M M M列组成, ...

  4. POJ 1185 炮兵阵地(状压DP)

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

  5. POJ 1185 炮兵阵地 状压dp

    题目链接: http://poj.org/problem?id=1185 炮兵阵地 Time Limit: 2000MS Memory Limit: 65536K 问题描述 司令部的将军们打算在N*M ...

  6. POJ 1185炮兵阵地 (状压DP)

    题目链接 POJ 1185 今天艾教留了一大堆线段树,表示做不动了,就补补前面的题.QAQ 这个题,我第一次写还是像前面HDU 2167那样写,发现这次影响第 i 行的还用i-2行那样,那以前的方法就 ...

  7. poj - 1185 炮兵阵地 状压DP 解题报告

    炮兵阵地 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 21553   Accepted: 8363 Description ...

  8. POJ 1185 炮兵阵地 经典的 状态压缩dp

    炮兵阵地 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 16619   Accepted: 6325 Description ...

  9. 【简●解】POJ 1185,LG P2704【炮兵阵地】

    POJ 1185,LG P2704[炮兵阵地] 状压经典入门. [传送门] POJ 1185 洛谷 P2704 [题目大意] 司令部的将军们打算在 \(N\times M\) 的网格地图上部署他们的炮 ...

随机推荐

  1. jdbcTemplate的配置

    相关jar 包 package sfk.bbs.test.springjsbctempletTest; import static org.junit.Assert.*; import java.sq ...

  2. JAVA反射机制—学习总结

    最近收到很多关于Java反射机制的问题留言,其实Java反射机制技术方面没有太多难点,或许是大家在学习过程中遗漏了细小知识点,导致一些问题无法彻底理解,现在我们简单的总结一下,加深印象.什么是反射机制 ...

  3. POJ3259Wormholes(判断是否存在负回路)

    Wormholes Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 38300   Accepted: 14095 Descr ...

  4. C# 抓取网页Html源码 (网络爬虫)

    http://www.cnblogs.com/wxxian001/archive/2011/09/07/2169519.html 刚刚完成一个简单的网络爬虫,因为在做的时候在网上像无头苍蝇一样找资料. ...

  5. Struts2 自定义Result

    注意:我只要是解决自定义返回Json 和异常处理问题 新建一个类 AjaxResult   继承 StrutsResultSupport 看看代码吧 public class AjaxResult e ...

  6. stl 迭代器(了解)

    STL 主要是由 containers(容器),iterators(迭代器)和 algorithms(算法)的 templates(模板)构成的. 对应于它们所支持的操作,共有五种 iterators ...

  7. Laravel教程 二:路由,视图,控制器工作流程

    Laravel教程 二:路由,视图,控制器工作流程 此文章为原创文章,未经同意,禁止转载. View Controller 上一篇教程我们走了那么长的路,终于把Laravel安装好了,这一篇教程我们就 ...

  8. PHP array_intersect() 函数

    PHP Array 函数 定义和用法 array_intersect() 函数返回两个或多个数组的交集数组. 结果数组包含了所有在被比较数组中,也同时出现在所有其他参数数组中的值,键名保留不变. 注释 ...

  9. 保存知乎收藏夹功能的NodeJS版本

    前两天发现知乎收藏夹中的答案正在不断减少..看来需要保存一下了,但之前别人的方式是用chrome插件(浏览器无法自动保存本地文件)+wget前后端配合来完成这个工作的,而且还有一些缺点(比如保存的ht ...

  10. 三种dedecms调用相关文章的方法

    在文章的末尾或侧边栏添加相关文章可以提高用户的黏度,提高pv,增加se的好印象(哈哈),那么dedecms如何调用相关文章呢?有三种方法可以实现. 第一种dedecms调用相关文章的方法,用默认的li ...