D. Lizard Era: Beginning(折半搜索)
Posted Harris-H
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了D. Lizard Era: Beginning(折半搜索)相关的知识,希望对你有一定的参考价值。
D. Lizard Era: Beginning(折半搜索)
思路比较显然就是折半搜索,关键是如何用 m p mp mp记录前一半的状态。
考虑用 p a i r pair pair到 p a i r pair pair的映射。因为我们只需要 4 4 4个变量 a , b , c , p a t h a,b,c,path a,b,c,path。
因为要求最后尽可能大,所以第一个 p a i r pair pair可表示为: a − b , a − c a-b,a-c a−b,a−c。
第二个 p a i r pair pair表示为: a , p a t h a,path a,path。
这样当第一个 p a i r pair pair相同时, a a a尽可能大即可。
如何判断是否达到题目要求呢?
( a , b , c ) , ( x , y , z ) (a,b,c),(x,y,z) (a,b,c),(x,y,z)
a + x = b + y = c + z a+x=b+y=c+z a+x=b+y=c+z。
( a − b , a − c ) = ( y − x , z − x ) (a-b,a-c)=(y-x,z-x) (a−b,a−c)=(y−x,z−x)。
因此只需判断 ( y − x , z − x ) (y-x,z-x) (y−x,z−x)是否出现过即可。
至于输出答案,就利用三进制即可。
参考代码
#include<bits/stdc++.h>
using namespace std;
namespace Acc{
const int N=30;
int v[N][3],r=-1e9,p1,p2,st[N],tp,n,m;
char h[3]={'L','M','W'};
map<pair<int,int>,pair<int,int>>mp;
void dfs1(int d,int a,int b,int c,int path){
if(d==m+1){
pair<int,int>x={a-b,a-c},y={a,path};
if(!mp.count(x))mp[x]=y;else if(mp[x].first<a)mp[x]=y;
return;
}
dfs1(d+1,a,b+v[d][1],c+v[d][2],path*3);
dfs1(d+1,a+v[d][0],b,c+v[d][2],path*3+1);
dfs1(d+1,a+v[d][0],b+v[d][1],c,path*3+2);
}
void dfs2(int d,int x,int y,int z,int path){
if(d==n+1){
pair<int,int>a={y-x,z-x};int b;
if(mp.count(a)&&r<(b=mp[a].first+x))r=b,p1=mp[a].second,p2=path;
return;
}
dfs2(d+1,x,y+v[d][1],z+v[d][2],path*3);
dfs2(d+1,x+v[d][0],y,z+v[d][2],path*3+1);
dfs2(d+1,x+v[d][0],y+v[d][1],z,path*3+2);
}
void work(){
cin>>n,m=n>>1;
for(int i=1;i<=n;i++)for(int j=0;j<3;j++)cin>>v[i][j];
dfs1(1,0,0,0,0),dfs2(m+1,0,0,0,0);
if(r==-1e9)puts("Impossible"),exit(0);
for(int i=m+1;i<=n;i++,p2/=3)st[++tp]=p2%3;
for(int i=1;i<=m;i++,p1/=3)st[++tp]=p1%3;
for(;tp;puts(""),tp--)for(int j=0;j<3;j++)if(j!=st[tp])putchar(h[j]);
}
}
int main(){
return Acc::work(),0;
}
以上是关于D. Lizard Era: Beginning(折半搜索)的主要内容,如果未能解决你的问题,请参考以下文章
[codeforces] 585D Lizard Era: Beginning || 双向dfs
IIPP迷你项目“Rock-paper-scissor-lizard-Spock”