• 【URAL 1519】Formula 1


    http://acm.timus.ru/problem.aspx?space=1&num=1519
    调了好久啊。参考(抄)的iwtwiioi的题解
    如果想要题解,题解在《基于连通性状态压缩的动态规划问题》。
    我肯定讲得不如题解清楚QAQ,所以还是不讲了(╯‵□′)╯︵┻━┻
    连通性状压得用bfs扩展同时hash表判重。为什么呢?
    因为状态太多数组存不下,只能用hash表存有用的状态,没错就是这样!!!
    感觉代码量比普通状压高了不少QAQ
    这么复杂,还是典型例题→_→。
    时间复杂度(O(n*m^22^{(m+1)*2}))
    我用的四进制表示状态,常数比三进制小。bfs和hash表应该能跑得比理论复杂度快得多吧。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define BIT(a, b) ((a) << ((b) << 1))
    #define CLR(a, b) (a ^= ((a) & BIT(3, b)))
    #define GET(a, b) (((a) >> ((b) << 1)) & 3)
    using namespace std;
    const int M = 1000007;
    typedef long long ll;
    
    bool mp[12][12], flag;
    
    ll ans = 0;
    
    int n, m, lan = 0, lam = 0;
    
    struct node {
    	int to[M], hash[M], cnt;
    	ll sum[M];
    	
    	node() {
    		memset(to, 0, sizeof(to));
    		memset(hash, -1, sizeof(hash));
    		memset(sum, 0, sizeof(sum));
    		cnt = 0;
    	}
    	
    	void ins(int s, ll num) {
    		int pos = s % M; flag = false;
    		while (true) {
    			if (hash[pos] == -1) {hash[pos] = s; flag = true; break;}
    			if (hash[pos] == s) break;
    			++pos; if (pos == M) pos = 0;
    		}
    		sum[pos] += num;
    		if (flag) to[++cnt] = pos;
    	}
    	
    	void clr() {while (cnt) {hash[to[cnt]] = -1; sum[to[cnt]] = 0; --cnt;}}	
    } T1, T2;
    
    int cc = 0, nn;
    
    int find(int s, int tmp, int d) {
    	if (d) {
    		for (int i = tmp; i < m; ++i) {
    			nn = GET(s, i);
    			if (nn == 1) ++cc;
    			if (nn == 2) --cc;
    			if (cc == 0) return i;
    		}
    	} else {
    		for (int i = tmp; i >= 0; --i) {
    			nn = GET(s, i);
    			if (nn == 2) ++cc;
    			if (nn == 1) --cc;
    			if (cc == 0) return i;
    		}
    	}
    }
    
    int l, u, d, r, pos;
    
    bool getnxt(int s, int row, int col, bool U, bool D, bool L, bool R, int &t, ll sum) {
    	if ((row == 0 && U) || (col == 0 && L) || (row == n - 1 && D) || (col == m - 1 && R)) return false;
    	if ((mp[row + 1][col] && D) || (mp[row][col + 1] && R)) return false;
    	if (row == lan && col == lam && (R || D)) return false;
    	l = GET(s, col); u = GET(s, col + 1);
    	if ((((bool) u) != U) || (((bool) l) != L)) return false;
    	t = s; CLR(t, col + 1); CLR(t, col);
    	
    	d = r = 0;
    	if (l == 0 && u == 0) {
    		if (D && R)
    			d = 1, r = 2;
    	} else if (l && u) {
    		if (l == 1 && u == 2) {
    			if (row != lan || col != lam) return false;
    			ans += sum;
    		} else if (l == 1 && u == 1) {
    			pos = find(s, col + 1, 1);
    			CLR(t, pos);
    			t |= BIT(1, pos);
    		} else if (l == 2 && u == 2) {
    			pos = find(s, col, 0);
    			CLR(t, pos);
    			t |= BIT(2, pos);
    		}
    	} else if (l && !u) {
    		if (D) d = l, r = 0;
    		if (R) r = l, d = 0;
    	} else if (!l && u) {
    		if (D) d = u, r = 0;
    		if (R) r = u, d = 0;
    	}
    	
    	t |= BIT(d, col); t |= BIT(r, col + 1);
    	if (col == m - 1) t <<= 2;
    	return true;
    }
    
    void bfs() {
    	node *q1, *q2; ll sum; int s, t;
    	q1 = &T1; q2 = &T2;
    	q1->ins(0, 1);
    	for (int row = 0; row < n; ++row)
    		for (int col = 0; col < m; ++col) {
    			q2->clr();
    			for (int i = q1->cnt; i >= 1; --i) {
    				sum = q1->sum[q1->to[i]];
    				s = q1->hash[q1->to[i]];
    				if (mp[row][col]) {
    					if (getnxt(s, row, col, 0, 0, 0, 0, t, sum))
    						q2->ins(t, sum);
    				} else {
    					if (getnxt(s, row, col, 1, 1, 0, 0, t, sum)) q2->ins(t, sum);
    					if (getnxt(s, row, col, 1, 0, 1, 0, t, sum)) q2->ins(t, sum);
    					if (getnxt(s, row, col, 1, 0, 0, 1, t, sum)) q2->ins(t, sum);
    					if (getnxt(s, row, col, 0, 1, 1, 0, t, sum)) q2->ins(t, sum);
    					if (getnxt(s, row, col, 0, 1, 0, 1, t, sum)) q2->ins(t, sum);
    					if (getnxt(s, row, col, 0, 0, 1, 1, t, sum)) q2->ins(t, sum);
    				}
    			}
    			swap(q1, q2);
    			if (row == lan && col == lam) return;
    		}
    }
    
    int main() {
    	scanf("%d%d", &n, &m);
    	char c;
    	for (int i = 0; i < n; ++i)	
    		for (int j = 0; j < m; ++j) {
    			for (c = getchar(); c != '*' && c != '.'; c = getchar());
    			if (c == '*') mp[i][j] = true;
    			else lan = i, lam = j;
    		}
    	
    	bfs();
    	printf("%lld
    ", ans);
    	return 0;
    }
    
  • 相关阅读:
    隆重推出PowerDesinger 12.1.0.1913破解补丁
    Glowcode 6.0 破解手记,.Net IL技术
    爬虫如何抓取到Asp.Net中__doPostBack获取新页面的数据
    谁是股市上的最大受益者
    带强名的.net程序反向工程后汇编中的问题总结
    让所有的实体店成为网店的体验店
    推出网站大鱼搜索
    利用搜索引擎技术抢注域名
    在程序中显示PDF文件不依赖于Arcobat Reader的PDF阅读器开发
    用开源Carrot2的后缀树算法做Web文本聚类
  • 原文地址:https://www.cnblogs.com/abclzr/p/6131902.html
Copyright © 2020-2023  润新知