模拟搜索真刺激
z_y_b 他真无敌
(又押韵了啊QwQ)
题目大意:
唔……直接粘原来的题目大意好了:
游戏中共有7种宝石,分别是红色(R),橙色(O),黄色(Y),绿色(G),蓝色(B),紫色(P)和白色(W)。
一副手牌由5张牌组成,在比较得分时,会先根据牌型特点进行分类,类别高的牌得分更高;在等级相同时,则会根据颜色的不同进一步判断。
手牌分类的依据如下:
编号 名称 特征 内部比较方式 举例
1 一对 恰好有2张牌颜色相同 先比较对子的颜色,相同时比较单张最大的颜色,再相同时比较单张次大的颜色,以此类推 RRWGB,WBGOB……
2 顺子 所有牌颜色均不同 先比较最大的颜色,相同时比较次大的颜色,以此类推 BWGOY,YGPWR……
3 两对 恰好有2对牌颜色相同 先比较较大的一对的颜色,相同时比较较小的一对的颜色,再相同时比较单张的颜色 OGBOB,RRPPW……
4 三条 恰好有3张牌颜色相同 先比较三张相同的颜色大小,相同时比较单张中较大的一张,再相同时比较单张中较小的一张 PWWOW,BBBYR……
5 葫芦 3张牌颜色相同,另外2张牌颜色相同 先比较相同的3张,相同时比较剩余2张 BBGGB,PRRRP……
6 四条 恰好4张牌颜色相同 先比较相同的4张,相同时再比较剩余的单张 YYYYO,RRWRR……
7 同花 所有牌颜色相同 比较颜色大小 BBBBB,PPPPP……
(额你问我为什么一对比顺子小?我也不知道啊游戏就是这么设定的qwq)
颜色的大小顺序是按照字母的字典序排序的,即B<G<O<P<R<W<Y。
手牌的顺序对于大小没有影响,当且仅当两副手牌按字典序排序后完全相同时,这两副手牌的得分相同。
这个游戏的界面是一个n行m列的棋盘,行数从上到下,列数从左到右依次增大,每个格子里有一个某种颜色的宝石。
另外,本题中还会提供长度为k的备用条,供宝石消除后补充用。
每次操作的规则如下:
1、选择一个格子中的宝石,将其颜色作为当前牌的颜色。
2、将这个宝石与上下左右某一方向的宝石交换。注意不能交换到棋盘外。
3、当且仅当能够消除原先选定的宝石时,本次操作是合法的。
消除的规则是:当一行或一列上有连续3个或更多颜色相同的宝石时,这些宝石将会被消除。注意一次移动可能会消除不止一处的宝石。
4、消除后,所有上方的宝石将会遵循重力下落(注意宝石位于的行数实际上会增大)。
5、此时棋盘上方出现了空格,将根据以下规则进行填充:
按照从左到右,从下到上,按列填充的顺序,依次从备用条中取出当前最前方的宝石填充进去。如果备用条已用完,将从开头处循环使用。
6、填充完毕后,如果依然存在可以消除的现象,将会继续消除、下落、填充,直至某次填充完毕后不存在可以继续消除的现象为止。
对于游戏中的其他特殊属性,本题目不再考虑。
某天,ldlsn发现这个游戏很好玩,于是向liuzhangfeiabc发起挑战:
两人将面对n,m,k相同的两个棋盘,每人操作5次,获得一副手牌,以手牌大小决胜负。
对于前10%的数据,只含有不超过3种颜色。
对于前20%的数据,只含有不超过4种颜色。
对于前40%的数据,只含有不超过5种颜色。
对于前60%的数据,只含有不超过6种颜色。
对于前30%的数据,n,m<=4。
对于前60%的数据,n,m<=6。
对于100%的数据,1<=n,m<=8,1<=T<=5,1<=k<=100。
数据保证:
1、初始局面不存在可以直接消除的现象;
2、对于玩家的任意合法决策,不存在陷入死循环等无法终局的情况。
3、可能存在这样的局面:对于玩家的任意合法决策,均无法实现5次操作。此时认为玩家的手牌分数最低,当两人均如此时仍视为平局。
当两人的决策均为最优时,谁能最终取胜?
题解:
然后我写了个Score类和Player类。
Score类用于计算一副手牌的权值(是一个pair<int,int>类型)。
Player类用于模拟棋盘。
加了一个剪枝是如果当前手牌不可能比当前答案大,就退出。
现在想想其实还应该写一个Board类,然后用Player类合并起来。
总之代码大概两百行,5个k左右的样子(其实还挺好写的):
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define mp make_pair
#define fir first
#define sec second
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
typedef pair<int,int> pii;
const int maxKind=7,terms=5;
inline int toi(char c)
{
switch(c)
{
case 'B':case 'b':return 1;
case 'G':case 'g':return 2;
case 'O':case 'o':return 3;
case 'p':case 'P':return 4;
case 'R':case 'r':return 5;
case 'W':case 'w':return 6;
case 'Y':case 'y':return 7;
default:assert(0);
}
return 0;
}
struct Score{
pii value;int cnt[10];
Score() {}
Score(int *a) { init(a); }
inline void init(int *a)
{
memset(cnt,0,sizeof(int)*(maxKind+1));
rep(i,1,terms) cnt[a[i]]++;int mx=0,x=0;
rep(i,1,maxKind) if(mx<cnt[i]) mx=cnt[i],x=i;
if(mx==5) { value=mp(7,x);return; }
if(mx==4)
{
value.fir=6,value.sec=x*10;
rep(i,1,maxKind) if(cnt[i]==1) value.sec+=i;
return;
}
if(mx==3)
{
value.fir=4,value.sec=0;
for(int i=1,t=1;i<=maxKind;i++)
if(cnt[i]==2) { value.fir=5,value.sec=x*10+i;return; }
else if(cnt[i]==1) value.sec+=i*t,t*=10;
value.sec+=x*100;return;
}
if(mx==1)
{
for(int i=1,t=1;i<=maxKind;i++)
if(cnt[i]) value.sec+=i*t,t*=10;
value.fir=2;return;
}
assert(mx==2);int t=0;
rep(i,1,maxKind) if(cnt[i]==2) t++;
if(t==1)
{
value.fir=1,value.sec=x*1000;
for(int i=1,t=1;i<=maxKind;i++)
if(cnt[i]==1) value.sec+=i*t,t*=10;
return;
}
value.fir=3,value.sec=0;
for(int i=1,t=10;i<=maxKind;i++)
if(cnt[i]==2) value.sec+=i*t,t*=10;
else if(cnt[i]) assert(cnt[i]==1),value.sec+=i;
}
inline bool operator<(const Score &s)const { return this->value<s.value; }
inline bool operator>(const Score &s)const { return this->value>s.value; }
inline bool operator==(const Score &s)const { return this->value==s.value; }
inline bool operator<=(const Score &s)const { return this->value<=s.value; }
inline bool operator>=(const Score &s)const { return this->value>=s.value; }
inline void show()const
{
cerr<<value.fir<<" "<<value.sec<<endl;
}
};
inline Score best_score(int *a,int len)
{
static int cnt[10],b[10];
memset(cnt,0,sizeof(int)*(maxKind+1));
rep(i,1,len) cnt[a[i]]++;int mx=0,x=0;
rep(i,1,maxKind) if(mx<=cnt[i]) mx=cnt[i],x=i;
rep(i,len+1,terms) cnt[x]++;int c=0;
rep(i,1,maxKind) rep(j,1,cnt[i]) b[++c]=i;
return Score(b);
}
int dx[10]={1,0,-1,0},dy[10]={0,-1,0,1};
struct Player{
static int n,m,k;int sav[10][20][20],top,a[10],bytsav[10],bytp;
char str[200];int b[20][20],del[20][20],byt[200];
Score score;Player():top(0){}
inline void save()
{
top++;
bytsav[top]=bytp;
rep(i,1,n) rep(j,1,m) sav[top][i][j]=b[i][j];
}
inline void back()
{
assert(top);
rep(i,1,n) rep(j,1,m) b[i][j]=sav[top][i][j];
bytp=bytsav[top];
top--;
}
inline void input()
{
rep(i,1,n)
{
scanf("%s",str+1);
rep(j,1,m) b[i][j]=toi(str[j]);
}
scanf("%s",str+1);
rep(i,1,k) byt[i]=toi(str[i]);
}
inline int next_byt()
{
bytp++;
if(bytp>k) bytp=1;
return byt[bytp];
}
inline bool can(int x,int y)
{
if(x-2>=1&&b[x][y]==b[x-1][y]&&b[x][y]==b[x-2][y]) return 1;
if(x+2<=n&&b[x][y]==b[x+1][y]&&b[x][y]==b[x+2][y]) return 1;
if(y-2>=1&&b[x][y]==b[x][y-1]&&b[x][y]==b[x][y-2]) return 1;
if(y+2<=m&&b[x][y]==b[x][y+1]&&b[x][y]==b[x][y+2]) return 1;
if(x-1>=1&&x+1<=n&&b[x][y]==b[x-1][y]&&b[x][y]==b[x+1][y]) return 1;
if(y-1>=1&&y+1<=m&&b[x][y]==b[x][y-1]&&b[x][y]==b[x][y+1]) return 1;
return 0;
}
inline bool Clear()
{
rep(i,1,n) rep(j,1,m) del[i][j]=0;bool ok=false;
rep(i,1,n) rep(j,1,m)
{
if(i+2<=n&&b[i][j]==b[i+1][j]&&b[i][j]==b[i+2][j]) del[i][j]=del[i+1][j]=del[i+2][j]=1;
if(j+2<=m&&b[i][j]==b[i][j+1]&&b[i][j]==b[i][j+2]) del[i][j]=del[i][j+1]=del[i][j+2]=1;
if(del[i][j]) ok=true;
}
return ok;
}
inline void Fall()
{
rep(j,1,m)
{
int t=n+1;
for(int i=n;i;i--)
if(del[i][j]) continue;
else b[--t][j]=b[i][j];
for(t--;t;t--) b[t][j]=next_byt();
}
}
inline void maintain()
{
while(Clear()) Fall();
}
inline bool canSwap(int x,int y,int s,int t)
{
swap(b[x][y],b[s][t]);
int ok=can(s,t);
swap(b[x][y],b[s][t]);
return ok;
}
inline void Swap(int x,int y,int s,int t)
{
swap(b[x][y],b[s][t]);
}
void dfs(int curTerms)
{
if(best_score(a,curTerms-1)<=score) return;
if(curTerms==terms+1) { score=max(score,Score(a));return; }
rep(i,1,n) rep(j,1,m) rep(d,0,3)
{
int x=i+dx[d],y=j+dy[d];
if(x<1||x>n||y<1||y>m||b[x][y]==b[i][j]) continue;
if(!canSwap(i,j,x,y)) continue;
a[curTerms]=b[i][j];
save();
Swap(i,j,x,y);
maintain();
dfs(curTerms+1);
back();
}
return;
}
inline void get_score()
{
score.value=mp(-1,0);
top=0;
bytp=0;
dfs(1);
}
inline void show()
{
debug(n)sp,debug(m)sp,debug(k)ln;
rep(i,1,k) cerr<<byt[i];cerr ln ln;
rep(i,1,n) { rep(j,1,m) cerr<<b[i][j];cerr ln; }
debug(bytp)ln ln;
debug(top)ln ln;
rep(i,1,top)
{
debug(i)ln;
rep(j,1,n) { rep(k,1,m) cerr<<sav[i][j][k];cerr ln; }
debug(bytsav[i])ln ln;
}
}
}p1,p2;
int Player::n=0,Player::m=0,Player::k=0;
int main()
{
int T;cin>>T;
while(T--)
{
cin>>Player::n>>Player::m>>Player::k;
p1.input(),p2.input();
p1.get_score(),p2.get_score();
if(p1.score==p2.score) printf("draw\n");
else if(p1.score>p2.score) printf("liuzhangfeiabc\n");
else printf("ldlsn\n");
}
return 0;
}