Luogu P4363 [九省联考2018]一双木棋chess
Posted wwwsfff
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Luogu P4363 [九省联考2018]一双木棋chess相关的知识,希望对你有一定的参考价值。
分析
显然每次轮廓线都是从左下到右上,所以方案数只有\\(C_{n+m}^{n}\\)次
暴力枚举状态,建出节点为状态的图
然后倒序DP即可
#include<bits/stdc++.h>
#define ll long long
#define pb push_back
const int INF=1e9;
using namespace std;
const int N=4e5+5;
int n,m,cnt,t[20],f[N],deg[N],a[20][20],b[20][20],num[N];
ll mi[20],S[N];
map<ll,int>mp;
struct A{int v,w;};
vector<A>V[N];
void dfs(int u,int lst,ll s) {
if(u>n) {
S[++cnt]=s;
mp[s]=cnt;
return;
}
for(int i=0;i<=lst;i++) {
dfs(u+1,i,s+mi[u-1]*i);
}
}
void init() {
mi[0]=1;
for(int i=1;i<=n;i++) mi[i]=mi[i-1]*11;
dfs(1,m,0);
for(int i=1;i<=cnt;i++) {
ll s=S[i];
for(int j=1;j<=n;j++) {
t[j]=s%11;
s/=11;
}
// printf("%d %lld %d %d %d\\n",i,S[i],t[1],t[2],num[i]);
for(int j=1;j<=n;j++) {
if(t[j]) {
if(t[j]<m&&(j==1||t[j]!=t[j-1])) {
s=S[i]+mi[j-1]; int k=mp[s];
num[k]=!num[i];
if(num[k]) V[k].pb((A){i,a[j][t[j]+1]});//V[i].pb((A){k,a[j][t[j]+1]});
else V[k].pb((A){i,-b[j][t[j]+1]});//V[i].pb((A){k,-b[j][t[j]+1]});
// printf("%d %d\\n",k,i);
}
} else {
// if(i==3) printf("%d\\n",j);
s=S[i]+mi[j-1]; int k=mp[s];
num[k]=!num[i];
if(num[k]) V[k].pb((A){i,a[j][1]});//V[i].pb((A){k,a[j][t[j]+1]});
else V[k].pb((A){i,-b[j][1]});//V[i].pb((A){k,-b[j][t[j]+1]});
// printf("%d %d\\n",k,i);
break;
}
}
f[i]=INF;
}
}
queue<int>q;
void bfs(int s) {
q.push(s); f[s]=0;
while(!q.empty()) {
int u=q.front(); q.pop();
for(A v:V[u]) {
if(f[v.v]==INF){
f[v.v]=f[u]+v.w;
q.push(v.v);
}
if(num[u]) f[v.v]=max(f[v.v],f[u]+v.w);
else f[v.v]=min(f[v.v],f[u]+v.w);
}
}
}
int main() {
scanf("%d%d",&n,&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]);
}
init();
bfs(cnt);
printf("%d\\n",f[1]);
return 0;
}
以上是关于Luogu P4363 [九省联考2018]一双木棋chess的主要内容,如果未能解决你的问题,请参考以下文章