zoukankan      html  css  js  c++  java
  • [九省联考2018]一双木棋

    Description

    Luogu4363
    BZOJ5248

    Solution

    可以发现,先手要最大化分差,后手要最小化分差,数据范围又很小,不像找规律,所以应该用min-max搜索。然后,棋子其实是左上方的一块区域,所以可以hash一下轮廓线,记忆化搜索就行了。

    Code

    #include <cstdio>
    #include <map>
    #define base (m+1)
    
    typedef unsigned long long LL;
    const int N = 11;
    const int INF = 0x3f3f3f3f;
    
    int ln[N], n, m;
    std::map<LL, int> f;
    int B[N][N], A[N][N];
    
    bool is_B() { int p=0; for (int i = 1; i <= n; ++i) p += ln[i]; return p&1; }
    LL hash() {
    	LL st=0;
    	for (int i = 1; i <= n; ++i) st = st * base + ln[i];
    	return st;
    }
    void unhash(LL st) {
    	for (int i = n; i; --i) ln[i] = st % base, st /= base;
    }
    int dfs(LL st) { // 表示在st状态下双方均执行最优策略的答案 
    	if (f.count(st)) return f[st];
    	unhash(st);
    	bool b = is_B(); int ret = b?INF:-INF;
    	for (int i = 1; i <= n; ++i) if (ln[i-1] > ln[i]) { 
    		ln[i]++;
    		LL nxt = hash();
    		ret = b?std::min(ret, dfs(nxt) - B[i][ln[i]]):std::max(ret, dfs(nxt) + A[i][ln[i]]);
    		ln[i]--;
    	}
    	return f[st] = ret;
    }
    
    int main() {
    	scanf("%d%d", &n, &m);
    	ln[0] = m;
    	for (int i = 1; i <= n; ++i) {
    		for (int j = 1; j <= m; ++j) {
    			scanf("%d", &A[i][j]);
    		}
    	}
    	for (int i = 1; i <= n; ++i) {
    		for (int j = 1; j <= m; ++j) {
    			scanf("%d", &B[i][j]);
    		}
    	} 
    	for (int i = 1; i <= n; ++i) ln[i] = m;
    	f[hash()] = 0;
    	for (int i = 1; i <= n; ++i) ln[i] = 0;
    	dfs(0);
    	printf("%d
    ", f[0]);
    	return 0;
    }
    
  • 相关阅读:
    ajax
    Django之modelform组件
    Django之form组件
    orm事务与锁
    orm之多表操作
    orm之单表操作
    Django之orm
    Django之模板系统
    Django之视图
    hdu5698瞬间移动(杨辉三角+快速幂+逆元)
  • 原文地址:https://www.cnblogs.com/wyxwyx/p/jslk2018chess.html
Copyright © 2011-2022 走看看