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

解题报告:

传送门!

因为看到$n,m$范围特别小,,,所以直接考虑爆搜$(bushi$

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

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

所以直接对每一步枚举所有状态,因为这样最优性的问题显然有每个状态对应唯一确定答案,所以直接对每个状态算出这个状态的答案,然后取最大/最小值就好

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

所以就记搜一下

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

然后这样似乎会$T$,,,至少我之前交$T$了$kk$

然后我们最近考试又考到这题了,,,为了避免写记搜然后$T$掉我就写了个轮廓线$dp$(也许是轮廓线$dp$,,,?我不知道轮廓线$dp$到底是啥昂$kk$),就记横0竖1,设$f_i$表示状态$i$之后的所有步数的$min$/$max$,转移下就成

其实中心思想差不多?但是快些$QwQ$

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

 

洛谷$P4363$ 一双木棋$chess$ [九省联考2018] 搜索+$hash$/$dp$洛谷$P4363$ 一双木棋$chess$ [九省联考2018] 搜索+$hash$/$dp$
 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

 

洛谷$P4363$ 一双木棋$chess$ [九省联考2018] 搜索+$hash$/$dp$洛谷$P4363$ 一双木棋$chess$ [九省联考2018] 搜索+$hash$/$dp$
#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

 

相关文章:

  • 2022-03-07
  • 2022-03-08
  • 2021-06-09
  • 2022-01-13
  • 2021-10-23
  • 2021-12-26
  • 2022-01-27
猜你喜欢
  • 2021-08-04
  • 2022-12-23
  • 2021-10-24
  • 2021-10-06
  • 2022-02-15
  • 2022-01-09
  • 2021-05-28
相关资源
相似解决方案