洛谷$P4363$ 一双木棋$chess$ [九省联考2018] 搜索+$hash$/$dp$

正解:记搜+$hash$/$dp$

解题报告:

传送门!node

由于看到$n,m$范围特别小,,,因此直接考虑爆搜$(bushi$
c++

先考虑爆搜以后再想优化什么的嘛$QwQ$ide

首先对这种都要最优的,就能够直接把答案设为针对某一方,而后题目就会变成,轮流的,一次最大一次最小这样子(,,,好像表述得不太好,,,无论了$QAQ$优化

因此直接对每一步枚举全部状态,由于这样最优性的问题显然有每一个状态对应惟一肯定答案,因此直接对每一个状态算出这个状态的答案,而后取最大/最小值就好spa

而后继续考虑,这样显然是会$T$的?3d

因此就记搜一下code

只是考虑记搜怎么存,,,由于这是个轮廓线,因此直接$hash$一下,把轮廓线转化成$m$进制数存到$map$里这样的blog

而后这样彷佛会$T$,,,至少我以前交$T$了$kk$
get

而后咱们最近考试又考到这题了,,,为了不写记搜而后$T$掉我就写了个轮廓线$dp$(也许是轮廓线$dp$,,,?我不知道轮廓线$dp$究竟是啥昂$kk$),就记横0竖1,设$f_i$表示状态$i$以后的全部步数的$min$/$max$,转移下就成hash

其实中心思想差很少?可是快些$QwQ$

而后分别放下那个$80pts$的和$100pts$的$code$趴

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define il inline
 4 #define ll long long
 5 #define gc getchar()
 6 #define ri register int
 7 #define rc register char
 8 #define rb register bool
 9 #define rp(i,x,y) for(ri i=x;i<=y;++i)
10 #define my(i,x,y) for(ri i=x;i>=y;--i)
11 
12 const int N=10+5,bas=11,inf=1e9;
13 int n,m,a[N][N],b[N][N],ln[N];
14 ll poww[N]={1},all;
15 map<ll,int>M;
16 
17 il int read()
18 {
19     rc ch=gc;ri x=0;rb y=1;
20     while(ch!='-' && (ch>'9' || ch<'0'))ch=gc;
21     if(ch=='-')ch=gc,y=0;
22     while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc;
23     return y?x:-x;
24 }
25 il bool jud(){ri ret=0;rp(i,1,n)ret+=ln[i];return ret&1;}
26 il void unhsh(ll ret){my(i,n,1)ln[i]=ret%bas,ret/=bas;}
27 il ll hsh(){ll ret=0;rp(i,1,n)ret=ret*bas+ln[i];return ret;}
28 int dfs(ll zt)
29 {
30     if(M.count(zt))return M[zt];
31     unhsh(zt);bool opt=jud();ri ret=opt?inf:-inf;
32     rp(i,1,n)
33     {
34         if(ln[i]>=ln[i-1])continue;
35         ++ln[i];ll nw=hsh();
36         ret=opt?min(ret,dfs(nw)-b[i][ln[i]]):max(ret,dfs(nw)+a[i][ln[i]]);
37         --ln[i];
38     }
39     return M[zt]=ret;
40 }
41  
42 int main()
43 {
44 //     freopen("4363.in","r",stdin);freopen("4363.out","w",stdout);
45     n=read();ln[0]=m=read();rp(i,1,n)rp(j,1,m)a[i][j]=read();rp(i,1,n)rp(j,1,m)b[i][j]=read();
46     rp(i,1,n)all=all*bas+m;M[all]=0;printf("%d\n",dfs(0));
47     return 0;
48 }
View Code

 

#include<bits/stdc++.h>
using namespace std;
#define il inline
#define gc getchar()
#define ri register int
#define rb register bool
#define rc register char
#define rp(i,x,y) for(ri i=x;i<=y;++i)
#define my(i,x,y) for(ri i=x;i>=y;--i)

const int N=(1<<21)+1000,M=25,inf=1e9;
int n,m,f[N],a[M][M],b[M][M];
struct node{int pos[M],sum;node(){memset(pos,0,sizeof(pos));sum=0;}};
bool vis[N];

il int read()
{
    rc ch=gc;ri x=0;rb y=1;
    while(ch!='-' && (ch>'9' || ch<'0'))ch=gc;
    if(ch=='-')ch=gc,y=0;
    while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc;
    return y?x:-x;
}
il node jy(ri zt)
{
    node nw;ri nwpos=m;
    while(zt){if(zt&1)++nw.pos[nwpos];else --nwpos,nw.pos[nwpos]=nw.pos[nwpos+1];zt>>=1;}
    my(i,nwpos-1,1)nw.pos[i]=nw.pos[i+1];rp(i,1,m)nw.sum+=nw.pos[i];return nw;
}
il int ys(node nw){ri dat=0;rp(i,1,m){dat<<=1;while(nw.pos[i]>nw.pos[i+1])dat=dat<<1|1,--nw.pos[i];}return dat;}
int dp(ri zt)
{
    if(zt==(1<<n)-1)return 0;if(vis[zt])return f[zt];
    node nw=jy(zt);nw.pos[0]=n;
    if(!(nw.sum&1)){f[zt]=-inf;rp(i,1,m)if(nw.pos[i-1]>nw.pos[i])++nw.pos[i],f[zt]=max(f[zt],dp(ys(nw))+a[nw.pos[i]][i]),--nw.pos[i];}
    else{f[zt]=inf;rp(i,1,m)if(nw.pos[i-1]>nw.pos[i])++nw.pos[i],f[zt]=min(f[zt],dp(ys(nw))-b[nw.pos[i]][i]),--nw.pos[i];}
    vis[zt]=1;return f[zt];
}

int main()
{
    //freopen("chess.in","r",stdin);freopen("chess.out","w",stdout);
    n=read();m=read();rp(i,1,n)rp(j,1,m)a[i][j]=read();rp(i,1,n)rp(j,1,m)b[i][j]=read();
    printf("%d\n",dp(0));
    return 0;
}
View Code
相关文章
相关标签/搜索