1. 程式人生 > >[九省聯考2018]一雙木棋chess——搜索+哈希

[九省聯考2018]一雙木棋chess——搜索+哈希

tdi 其它 namespace typedef span http sin 全局 ref

題目:bzoj5248 https://www.lydsy.com/JudgeOnline/problem.php?id=5248

   洛谷P4363 https://www.luogu.org/problemnew/show/P4363

終於A了(雖然得開O2才能過)!

其實就是暴搜,用一個 n+1 進制數表示狀態,進行最優策略轉移即可;

註意 cnt[] 如果開成全局變量就不能每次翻譯那個 n+1 進制數,否則會影響其它層的搜索;

(還有一種神奇的狀態壓縮是有幾個用了 k 個1的列,就在第 k 個0後面加幾個1……)

代碼如下:

#include<iostream>
#include<cstdio>
#include
<cstring> #include<map> using namespace std; typedef long long ll; map<ll,ll>mp; map<ll,bool>vis; int n,m,s[3][15][15],inf=1e9,cnt[15]; ll pw(int a,int b) { ll ret=1; while(b){if(b&1)ret*=a;a*=a;b>>=1;} return ret; } ll dfs(ll x,bool f) { if(vis[x])return
mp[x]; vis[x]=1;mp[x]=-inf;ll tx=x; // for(int i=m;i;i--)cnt[i]=tx%(n+1),tx/=(n+1); if(cnt[m]==n)return mp[x]=0; for(int i=1;i<=m;i++) { if(cnt[i]==n||(i>1&&cnt[i-1]<=cnt[i]))continue; cnt[i]++; ll y=x+pw(n+1,m-i); mp[x]=max(mp[x],s[f][cnt[i]][i]-dfs(y,!f)); cnt[i]
--; } return mp[x]; } int main() { scanf("%d%d",&n,&m); for(int k=0;k<=1;k++) for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&s[k][i][j]); printf("%lld",dfs(0,0)); }

[九省聯考2018]一雙木棋chess——搜索+哈希