Ural 1519. Formula 1 优美的插头DP
今天早上学了插头DP的思想和最基础的应用,中午就开始敲了,岐哥说第一次写不要看别人代码,利用自己的理解一点点得写出来,这样才锻炼代码能力!于是下午慢慢地构思轮廓,一点点地敲出主体代码,其实是很磨蹭的,由于要考虑好多东西,而且昨晚2点睡的有点困,最后终于磨蹭出来了,第一次的代码搓没关系,自己写的才重要。然后果然不出我所料,调试到了晚上才A了(一个郁闷的错误)。。。A的感觉真的是爽呀,虽然搞了差不多一天。当然自己写了自己想的代码后也要把代码优化,不然队友看不懂自己代码就囧了。。。
插头DP,建议大家想学的好好看看陈丹琦的国家集训队论文,这是个优美的DP。
http://www.docin.com/p-46797997.html
#include <stdio.h>
#include <string.h> #define LL __int64 const int mod = 10007; // 哈希表
struct HASH{
int head[mod+10], E, next[80000];
LL val[80000], cnt[80000]; void init() {
memset(head, -1, sizeof(head));
E = 0;
} int findhash(LL x) {
return (x%mod + mod)%mod;
} void add(LL x, LL sum) {
int u = findhash(x);
for(int i = head[u];i != -1;i = next[i]) if(val[i] == x) {
cnt[i] += sum;
return ;
}
val[E] = x;
cnt[E] = sum;
next[E] = head[u];
head[u] = E++;
} }biao1, biao2; int c[22], n, m, d[22];
// 编码
void get(LL x) {
for(int i = m+1;i >= 1; i--) {
c[i] = x&7;
x /= 8;
}
}
// 解码
LL getval() {
LL ret = 0;
for(int i = 1;i <= m+1; i++) {
ret |= d[i];
ret *= 8;
}
ret /= 8;
return ret ;
}
// 转化成最小表示法
void change() {
int vis[22];
memset(vis, 0, sizeof(vis));
int num = 1;
for(int i = 1;i <= m+1;i ++) {
if(!d[i]) continue;
if(!vis[d[i]]) {
vis[d[i]] = num;
d[i] = num++;
}
else {
d[i] = vis[d[i]];
}
}
} void fuzhi() {
for(int i = 1;i <= m+1;i ++) d[i] = c[i];
} char s[22][22]; int main() {
int i, j, k, l;
while(scanf("%d%d", &n, &m) != -1) {
for(i = 1;i <= n; i++)
scanf("%s", s[i]+1);
int tot = 0;
for(i = 1;i <= n; i++)
for(j = 1;j <= m; j++)
if(s[i][j] == '.') tot++;
if(tot%2==1 || tot < 4) {
puts("0");
continue;
}
int tox = -1, toy = -1;
for(i = 1;i <= n; i++)
for(j = 1;j <= m; j++) if(s[i][j] == '.') {
tox = i;
toy = j;
}
biao1.init();
biao1.add(0, 1);
LL ans = 0;
for(i = 1;i <= n; i++){
for(j = 0;j <= m; j++){
biao2.init();
for(l = 0;l < biao1.E; l++) {
get(biao1.val[l]);
if(j == m) {
for(int ii = 2;ii <= m+1; ii++) d[ii] = c[ii-1];
d[1] = 0;
change();
LL now = getval();
biao2.add(now, biao1.cnt[l]);
continue;
}
if(c[j+1] && !c[j+2]) { // 有左插头无上插头
if(s[i][j+1] != '.') continue;
if(j+2 <= m) {
fuzhi();
d[j+1] = 0;d[j+2] = c[j+1];
change();
LL now = getval();
biao2.add(now, biao1.cnt[l]);
}
if(i < n) {
fuzhi();
change();
LL now = getval();
biao2.add(now, biao1.cnt[l]);
}
}
else if(!c[j+1] && c[j+2]) { // 有上插头无左插头
if(s[i][j+1] != '.') continue;
if(i < n) {
fuzhi();
d[j+1] = c[j+2]; d[j+2] = 0;
change();
LL now = getval();
biao2.add(now, biao1.cnt[l]);
}
if(j+2 <= m) {
fuzhi();
change();
LL now = getval();
biao2.add(now, biao1.cnt[l]);
}
}
else if(!c[j+1] && !c[j+2]) { // 左和上都无插头
if(s[i][j+1] != '.') {
fuzhi();
change();
LL now = getval();
biao2.add(now, biao1.cnt[l]);
continue;
}
if(j+2 <= m && i < n) {
fuzhi();
d[j+1] = d[j+2] = 13;
change();
LL now = getval();
biao2.add(now, biao1.cnt[l]);
}
}
else { // 左和上都有插头 , 要判断左和上插头是否连通
if(c[j+2] == c[j+1]) {
int tot = 0;
for(int ii = 1;ii <= m+1; ii++) if(c[ii])
tot++;
if(tot == 2 && i == tox && j+1 == toy) ans += biao1.cnt[l];
}
else {
if(s[i][j+1] != '.') continue;
fuzhi();
for(int ii = 1;ii <= m+1; ii++) if(ii != j+1 && ii != j+2 && d[ii] == d[j+1]) {
d[ii] = d[j+2];
break;
}
d[j+1] = d[j+2] = 0;
change();
LL now = getval();
biao2.add(now, biao1.cnt[l]);
}
}
}
biao1 = biao2;
}
}
printf("%I64d\n", ans);
}
return 0;
}
Ural 1519. Formula 1 优美的插头DP的更多相关文章
- 【BZOJ1814】Ural 1519 Formula 1 (插头dp)
[BZOJ1814]Ural 1519 Formula 1 (插头dp) 题面 BZOJ Vjudge 题解 戳这里 上面那个链接里面写的非常好啦. 然后说几个点吧. 首先是关于为什么只需要考虑三进制 ...
- 【BZOJ1814】Ural 1519 Formula 1 插头DP
[BZOJ1814]Ural 1519 Formula 1 题意:一个 m * n 的棋盘,有的格子存在障碍,求经过所有非障碍格子的哈密顿回路个数.(n,m<=12) 题解:插头DP板子题,刷板 ...
- bzoj1814 Ural 1519 Formula 1(插头dp模板题)
1814: Ural 1519 Formula 1 Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 924 Solved: 351[Submit][Sta ...
- bzoj 1814 Ural 1519 Formula 1 插头DP
1814: Ural 1519 Formula 1 Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 942 Solved: 356[Submit][Sta ...
- ural 1519 Formula 1(插头dp)
1519. Formula 1 @ Timus Online Judge 干了一天啊!!!插头DP入门. 代码如下: #include <cstdio> #include <cstr ...
- URAL 1519 Formula 1(插头DP,入门题)
Description Background Regardless of the fact, that Vologda could not get rights to hold the Winter ...
- HDU 1693 Eat the Trees(插头DP、棋盘哈密顿回路数)+ URAL 1519 Formula 1(插头DP、棋盘哈密顿单回路数)
插头DP基础题的样子...输入N,M<=11,以及N*M的01矩阵,0(1)表示有(无)障碍物.输出哈密顿回路(可以多回路)方案数... 看了个ppt,画了下图...感觉还是挺有效的... 参考 ...
- bzoj1814 Ural 1519 Formula 1(插头DP)
对插头DP的理解还不是很透彻. 先说一下肤浅的理解吧. 插头DP使用范围:指数级复杂度,且适用于解决网格图连通性问题,如哈密顿回路等问题.插头一般指每相邻2个网格的接口. 题目难度:一般不可做. 使用 ...
- bzoj 1814 Ural 1519 Formula 1 ——插头DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1814 普通的插头 DP .但是调了很久.注意如果合并两个 1 的话,不是 “把向右第一个 2 ...
随机推荐
- POJ 1185 状态压缩DP(转)
1. 为何状态压缩: 棋盘规模为n*m,且m≤10,如果用一个int表示一行上棋子的状态,足以表示m≤10所要求的范围.故想到用int s[num].至于开多大的数组,可以自己用DFS搜索试试看:也可 ...
- eclipse和cygwin搭建C++环境的修正版本
最近嫌弃切换系统麻烦.用了cygwin作为netbeans下C++的环境继续学习.我学的很渣,就不卖弄了. 网络上有很多这样的文章.经过对比和实验发现一个深坑.教程部分还是跟其他的一样,重点部分红字做 ...
- session与cookie的区别,有哪些不同之处
session与cookie的区别,根据自己的理解总结如下: (1)cookie是一种客户端的状态管理技术,将状态写在 浏览器端,而session是一种服务器端的状态管理技术,将 状态写在web服务器 ...
- SSO单点登录的实现原理
单点登录在现在的系统架构中广泛存在,他将多个子系统的认证体系打通,实现了一个入口多处使用,而在架构单点登录时,也会遇到一些小问题,在不同的应用环境中可以采用不同的单点登录实现方案来满足需求.我将以我所 ...
- nginx 基础文档
Nginx基础 1. nginx安装 2. nginx 编译参数详解 3. nginx安装配置+清缓存模块安装 4. nginx+PHP 5.5 5. nginx配置虚拟主机 6. ngi ...
- 那些年被我坑过的Python——邂逅与初识(第一章)
第一问:为什么学习Python? 虚妖说:为了还债,还技术债,很早接触编程,却一直徘徊,也码了很多代码,却从未真真学会编程! 第二问:什么是Python 是一种以简洁.优雅著称的解释型.动态.强类型的 ...
- Linux脚本
放置在/usr/local/sbin下面: 收到一个问题:"-bash XXX 没有权限":需要在此目录下执行chmod +x filename 收到一个问题:"-bas ...
- Java面试题相关内容
选择题(共5题,每题1.5分,共75分.多选题选不全或选错都不得分.)1. 以下属于面向对象的特征的是(C,D).(两项)A) 重载B) 重写C) 封装D) 继承 2. 以下代码运行输出是(C)pub ...
- HTML5之一HTML5简介
1.什么是HTML5? HTML5是HTML的新一代标准.以前版本的HTML标准4.01发布于1999. 自1999年以后,web已经有了翻天覆地的变化. 实际上HTML5仍旧是开发中的一个标准.但是 ...
- 欧拉计划 NO05 ps:4题想过,好做,但麻烦,有时间补充,这题也不难!
问题重述: 2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without an ...