洛谷$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
相關文章
相關標籤/搜索