题意:在棋盘上放一些炮使得它们不互相攻击。其实就是一行/一列最多放两个。

50分的数据中n,m至少有一个不超过8,比较直接的想法是对n/m中较小的一维做状态压缩,状态f[i][S1][S2]表示在前i行/列中,S1集合中的列/行放了1炮,S2集合中的列/行放了2炮。转移的时候,需要枚举第i行/列怎么放炮。这个时间复杂度好像炸天了….

仔细观察转移的过程,会发现S1和S2集合中的元素到底是谁其实无关紧要,我们只需要知道S1和S2的元素数目即可完成转移。所以可以把状态改成f[i][j][k]表示前i行有j列放了1炮,k列放了2炮的方案数,依然讨论第i行的方法,不过不需要逐个枚举方案。

因为闲得蛋疼把数组开成了两维,我的DP顺序比较奇怪…某个状态一定是从总炮数小于等于它的状态转移过来(等于的情况只有不放炮一种,写的时候不需要考虑,直接从之前继承下来),所以只要按照总炮数从大到小DP就行了。不过这题并没有卡内存,所以开成三维数组的话总是从i-1那一层转移过来,循环顺序怎样都没关系.

转移的时候,f[i][j][k]可以从f[i-1][j][k-1]转移过来,看起来是放一个炮的列数不变,放两个炮的列数+1,但不能理解成在一个空列上放两炮使得它变成有两炮的列,实际的过程是在一个空列放了一炮,在另一个之前有1炮的列上再放了1炮,因为在第i行每一列只能放一炮

我加了滚动数组之后864kb,404ms,bzoj上有人176kb就过了,而且跑得飞起,30ms.甚至还有0msAC的…不知道别人怎么做的,只能ym。

#include<cstdio>
const int maxn=,mod=;
int f[maxn][maxn];
int main(){
int n,m;scanf("%d%d",&n,&m);
f[][]=;
int lim=*m;
int ans=;
for(int i=;i<=n;++i){
for(int tot=lim;tot>=;--tot){//倒着枚举,类似于01背包的方法
for(int k=;k*<=tot;++k){
int j=tot-k*;
if(j>m)continue;
          //这一行放一炮
if(j!=){
f[j][k]+=(m-(k)-(j-))*1LL*f[j-][k]%mod;
} if(k!=){ f[j][k]+=(j+)*1LL*f[j+][k-]%mod; } //这一行放两炮
if(j>=){
f[j][k]+=(m-k-(j-))*1LL*(m-k-(j-))/2LL*f[j-][k]%mod;
}
if(k>=){
f[j][k]+=(j+)*(j+)/2LL*f[j+][k-]%mod;
}
if(k>=){
f[j][k]+=(m-j-k+)*1LL*(j)*f[j][k-]%mod;
}
f[j][k]%=mod;
if(i==n)ans=(ans+f[j][k])%mod;
}
}
}
printf("%d\n",ans);
return ;
}

bzoj1801[AHOI2009]CHESS中国象棋的更多相关文章

  1. BZOJ1801 Ahoi2009 chess 中国象棋 【DP+组合计数】*

    BZOJ1801 Ahoi2009 chess 中国象棋 Description 在N行M列的棋盘上,放若干个炮可以是0个,使得没有任何一个炮可以攻击另一个炮. 请问有多少种放置方法,中国像棋中炮的行 ...

  2. BZOJ1801 [Ahoi2009]chess 中国象棋(DP, 计数)

    题目链接 [Ahoi2009]chess 中国象棋 设$f[i][j][k]$为前i行,$j$列放了1个棋子,$k$列放了2个棋子的方案数 分6种情况讨论,依次状态转移. #include <b ...

  3. bzoj1801: [Ahoi2009]chess 中国象棋(DP)

    1801: [Ahoi2009]chess 中国象棋 题目:传送门 题解: 表示自己的DP菜的抠脚 %题解... 定义f[i][j][k]表示前i行 仅有一个棋子的有j列 有两个棋子的有k个 的方案数 ...

  4. [luogu2051][bzoj1801][AHOI2009]chess中国象棋【动态规划】

    题目描述 这次小可可想解决的难题和中国象棋有关,在一个N行M列的棋盘上,让你放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法.大家肯定很清楚,在中国象棋中炮的行走方式是 ...

  5. BZOJ1801 [Ahoi2009]chess 中国象棋 动态规划

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1801 题意概括 在N行M列的棋盘上,放若干个炮可以是0个,使得没有任何一个炮可以攻击另一个炮. 请 ...

  6. BZOJ1801:[Ahoi2009]chess 中国象棋

    Time Limit: 10 Sec  Memory Limit: 64 MB Description 在N行M列的棋盘上,放若干个炮可以是0个,使得没有任何一个炮可以攻击另一个炮. 请问有多少种放置 ...

  7. bzoj1801: [Ahoi2009]chess 中国象棋 dp

    题意:在N行M列的棋盘上,放若干个炮可以是0个,使得没有任何一个炮可以攻击另一个炮. 请问有多少种放置方法,中国像棋中炮的行走方式大家应该很清楚吧. 题解:dp[i][j][k]表示到了第i行,有j列 ...

  8. BZOJ1801 [Ahoi2009]chess 中国象棋 【dp】

    题目 在N行M列的棋盘上,放若干个炮可以是0个,使得没有任何一个炮可以攻击另一个炮. 请问有多少种放置方法,中国像棋中炮的行走方式大家应该很清楚吧. 输入格式 一行包含两个整数N,M,中间用空格分开. ...

  9. 【BZOJ1801】[Ahoi2009]chess 中国象棋 DP

    [BZOJ1801][Ahoi2009]chess 中国象棋 Description 在N行M列的棋盘上,放若干个炮可以是0个,使得没有任何一个炮可以攻击另一个炮. 请问有多少种放置方法,中国像棋中炮 ...

随机推荐

  1. java之yield(),sleep(),wait()区别详解

    1.sleep() 使当前线程(即调用该方法的线程)暂停执行一段时间,让其他线程有机会继续执行,但它并不释放对象锁.也就是说如果有synchronized同步快,其他线程仍然不能访问共享数据.注意该方 ...

  2. DispatcherHelper

    DispatcherHelper 通常,WPF 应用程序从两个线程开始:一个用于处理呈现, 一个用于管理 UI.呈现线程有效地隐藏在后台运行,而 UI 线程则接收输入.处理事件.绘制屏幕 以及运行应用 ...

  3. 什么是API

    我们从API的功能.分类.设计.实现.用户来看什么是API. API是应用程序组件之间通信的接口 --wiki:Application Programming Interface In compute ...

  4. 几种任务调度的 Java 实现方法与比较

    综观目前的 Web 应用,多数应用都具备任务调度的功能.本文由浅入深介绍了几种任务调度的 Java 实现方法,包括 Timer,Scheduler, Quartz 以及 JCron Tab,并对其优缺 ...

  5. EMV内核使用中的常见问题

    EMV内核在使用上会由于调用不当引起的许多问题,本文旨在基于内核LOG(也就是与IC卡交互的指令LOG)的基础上,对一些常见问题作初步的分析与解答,方便不熟悉EMV规范的同学参考. 本文的前提是你已经 ...

  6. c++返回值 注意事项

    1.不要返回指向局部变量或临时对象的引用.函数执行完毕后,局部变量和临时对象会消失,引用将指向不存在的数据 2.返回指向const对象的引用 使用const引用的常见原因是旨在提高效率,但对于何时采用 ...

  7. WPF 小技巧

    在使用mvvm模式开发时,对于Command的绑定是一件很伤脑筋的事情,尽管有强大的Blend类库支持: xmlns:Custom="http://www.galasoft.ch/mvvml ...

  8. [转]Windows 8.1删除这台电脑中视频/文档/下载等六个文件夹的方法

    Windows 8.1 已将“计算机”正式更名为“这台电脑”,当我们双击打开“这台电脑”后,也会很明显得发现另外一些变化:Windows 8.1  默认将视频.图片.文档.下载.音乐.桌面等常用文件夹 ...

  9. jsonp的优缺点

    转载:http://www.w3cfuns.com/notes/18271/df9ecd8f0ca5e523ae75745a3996c47c.html JSONP的优缺点        1.优点    ...

  10. window 运行指令(1)

    添加或删除程序 appwiz.cpl 管理工具 control admintools Bluetooth文件传送向导 fsquirt 计算器 calc 证书管理控制台 certmgr.msc 字符映射 ...