【插头DP】URAL 1519 Formula 1

通道:http://acm.timus.ru/problem.aspx?space=1&num=1519

题意:单回路,经过全部可达点,有阻碍点。

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int MAX_N = 13;
const int MAX_M = 13;
const int HASH = 10007;
const int MAX_S = 1000007; 

struct node {
	int head[HASH], nxt[MAX_S];
	long long dp[MAX_S], st[MAX_S];
	int cnt;
    void init() {
    	memset(head, -1, sizeof head);
        cnt = 0;
    }
    void push(long long s, long long v) {
    	int now = s % HASH;
        for(int i = head[now]; ~i; i = nxt[i]) if(st[i] == s) {
            dp[i] += v;
            return ;
        }
		st[cnt] = s; dp[cnt] = v;
        nxt[cnt] = head[now];
        head[now] = cnt++;
    }
}d[2];

int n, m;
int ex, ey;

int find_pos(long long s, int p) {
    return (s >> (p << 1)) & 3;
}

void tp(long long &s, int p, long long v) {
    s &= (~(3ll << (p << 1)));
    s |= (v << (p << 1));
}

int find_r(long long s, int p) {
    int cnt = 0;
    for(int i = p; i <= m; ++i) {
        if(find_pos(s, i) == 1) ++cnt;
        else if(find_pos(s, i) == 2) --cnt;
        if(!cnt) return i;
    }
}

int find_l(long long s, int p) {
    int cnt = 0;
    for(int i = p; i >= 0; --i) {
        if(find_pos(s, i) == 2) ++cnt;
        else if(find_pos(s, i) == 1) --cnt;
        if(!cnt) return i;
    }
}

void blank(int i, int j, int cur) {
    for(int k = 0; k < d[cur].cnt; ++k) {
        long long t = d[cur].st[k];
        int l = find_pos(t, j - 1), r = find_pos(t, j);
        if(l && r) {
            if(l == 1 && r == 1) {
                int tpos = find_r(t, j);
                tp(t, j - 1, 0); tp(t, j, 0); tp(t, tpos, 1);
                d[cur ^ 1].push(t, d[cur].dp[k]);
            } else if(l == 2 && r == 1) {
                tp(t, j - 1, 0); tp(t, j, 0);
                d[cur ^ 1].push(t, d[cur].dp[k]);
            } else if(l == 2 && r == 2) {
                int tpos = find_l(t, j - 1);
                tp(t, j - 1, 0); tp(t, j, 0); tp(t, tpos, 2);
                d[cur ^ 1].push(t, d[cur].dp[k]);
            } else { // 最后一个非障碍格子
            	tp(t, j - 1, 0); tp(t, j, 0);

                if (!t) if (i == ex && j == ey) d[cur ^ 1].push(t, d[cur].dp[k]);
            }
        } else if(l) {
            if(i < n) {
                d[cur ^ 1].push(t, d[cur].dp[k]);
            }
            if(j < m) {
                tp(t, j - 1, 0); tp(t, j, l);
                d[cur ^ 1].push(t, d[cur].dp[k]);
            }
        } else if(r) {
            if(j < m) {
                d[cur ^ 1].push(t, d[cur].dp[k]);
            }
            if(i < n) {
                tp(t, j - 1, r); tp(t, j, 0);
                d[cur ^ 1].push(t, d[cur].dp[k]);
            }
        } else { // 新建
            if(i < n && j < m) {
                tp(t, j - 1, 1); tp(t, j, 2);
                d[cur ^ 1].push(t, d[cur].dp[k]);
            }
        }
    }
} 

void block(int i, int j, int cur) {
	for (int k = 0; k < d[cur].cnt; ++k) {
		long long t = d[cur].st[k];
		int l = find_pos(t, j - 1), r = find_pos(t, j);
        if (!l && !r) d[cur ^ 1].push(t, d[cur].dp[k]);
	}
} 

char str[17];
int a[MAX_N][MAX_M];

int main() {
    while (2 == scanf("%d%d", &n, &m)) {
    	memset(a, 0, sizeof a);
    	ex = ey = -1;
    	for (int i = 1; i <= n; ++i) {
    		scanf("%s", str + 1);
    		for (int j = 1; j <= m; ++j) {
    			if (str[j] == ‘.‘) {
    				a[i][j] = 1;
    				ex = i, ey = j;
    			}
    		}
    	}
    	if (ex == -1) puts("0");
    	else {
	    	int cur = 0;
	    	d[cur].init();
	    	d[cur].push(0, 1);
	    	long long ans = 0;
	    	for (int i = 1; i <= n; ++i) {
	    		for (int j = 1; j <= m; ++j) {
	    			d[cur ^ 1].init();
	    			if (a[i][j]) blank(i, j, cur);
	    			else block(i, j, cur);
	    			cur ^= 1;
	    		}
	    		for(int k = 0; k < d[cur].cnt; ++k) {
		            d[cur].st[k] <<= 2;
		        }
	    	}
	    	for (int i = 0; i < d[cur].cnt; ++i)
	    		ans += d[cur].dp[i];
	    	printf("%I64d\n", ans);
    	}
    }
    return 0;
}

  

时间: 2025-01-22 05:18:55

【插头DP】URAL 1519 Formula 1的相关文章

bzoj1814: Ural 1519 Formula 1 2011-12-20

1814: Ural 1519 Formula 1Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 263  Solved: 70[Submit][Status][Discuss]DescriptionRegardless of the fact, that Vologda could not get rights to hold the Winter Olympic games of 20**, it is well- known, that the 

【URAL 1519】【插头dp模板】Formula 1

1519. Formula 1 Time limit: 1.0 second Memory limit: 64 MB Background Regardless of the fact, that Vologda could not get rights to hold the Winter Olympic games of 20**, it is well-known, that the city will conduct one of the Formula 1 events. Surely

URAL - 1519 Formula 1 (插头DP)

这里写链接内容 刚开始学插头dp好吃力,看了别人的代码有点看不懂,所以就参考了别人的代码,写了注释,希望有帮助 如果看不懂可以问 //下面所说的情况全在论文中的第13页 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 13 #define S1 14000 #define S2 1600000 struct Queue{ int opt; long

URAL 1519 Formula 1 (插头DP,常规)

题意:给一个n*m的矩阵,格子中是'*'则是障碍格子,不允许进入,其他格子都是必走的格子,所走格子形成一条哈密顿回路,问有多少种走法? 思路: 本来是很基础的题,顿时不知道进入了哪个坑.这篇插头DP的文章够详细,推荐一看(最好不要照抄代码). 细节要小心,比如输出用I64d,必须用long long,判断是否无哈密顿回路,位操作等等. 这次仍然用括号表示法,1表示(,2表示). 1 #include <bits/stdc++.h> 2 #define pii pair<int,int&g

【bzoj1814】Ural 1519 Formula 1 插头dp

题目描述 一个 m * n 的棋盘,有的格子存在障碍,求经过所有非障碍格子的哈密顿回路个数. 输入 The first line contains the integer numbers N and M (2 ≤ N, M ≤ 12). Each of the next N lines contains M characters, which are the corresponding cells of the rectangle. Character "." (full stop)

bzoj1814: Ural 1519 Formula 1 动态规划 插头dp

dbzoj依然爆炸 题目描述 一个 m * n 的棋盘,有的格子存在障碍,求经过所有非障碍格子的哈密顿回路个数. 输入 The first line contains the integer numbers N and M (2 ≤ N, M ≤ 12). Each of the next N lines contains M characters, which are the corresponding cells of the rectangle. Character "." (f

bzoj 1814: Ural 1519 Formula 1【插头dp】

设f[i][j][s]为轮廓线推到格子(i,j),状态为s的方案数 括号表示一段线的左端和右端,表示成左括号和右括号,状压的时候用1和2表示,0表示已经闭合 下面的蓝线是黄色格子的轮廓线,dp转移要把它转到橙色轮廓线,设已经在状压的s中取到两条边的状态记为b1,b2 然后分很多情况讨论: (i,j)是障碍:那就只能什么都不放的转移,也就是只能从b1=0,b2=0转移到新轮廓线的b1=0,b2=0 if(!a[i][j]) { if(!b1&&!b2) add(x,v); } b1=0,b2

bzoj 1814: Ural 1519 Formula 1 插头dp经典题

用的括号序列,听说比较快. 然并不会预处理,只会每回暴力找匹配的括号. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define N 199917 6 #define ll long long 7 #define bp 1<<bit[j-1] 8 #define bq 1<<bit[j] 9 using nam

[URAL 1519] Formula 1 轮廓线DP 括号序列

题意 n * m 的矩形, 有坏点, 问哈密顿回路数量. n, m <= 11 . 分析 1. 确立状态 我们考虑轮廓线DP. 为此, 我们要刻画并量化轮廓线的相关信息: ① 插头是否存在? ② 插头的连通性. 我们发现: 插头一一对应, 且互不相交. 于是考虑使用括号序列刻画轮廓线. 至于量化, 我们将一个括号序列当做一个三进制数即可. 2. 转移 从上一行的最后一个, 转移到当前行的第一个: 位移. 当前格子为坏点: 对于没有插头插到当前点的状态原样复制. 否则: (1) L = # , R