赞
踩
目前天梯到了20/343,估计上限是15名左右。
1、代码量在600-800行左右,为什么是“左右”,因为一开始都是用STL写的,用了queue和各种vector,毕竟限时都是一秒,为了增大运算次数。测试之后,一秒内计算次数在10万次上下。
2、思路:蒙特卡洛树套价值评估。
3、关于价值评估:
每一个点的价值根据周围的情况不同要有不同的估值,根据上下左右四个点的状态(是否可行走)。分别估值为
switch(vis_sum){
case 1:weight[which][x][y]=1.0;break;
case 2:weight[which][x][y]=1.2;break;
case 3:weight[which][x][y]=1.6;break;
case 4:weight[which][x][y]=2.0;break;
}
1)价值评估过程用bfs,根据最短路是否可达,判定某地图位置是否可达,并且计算最短距离。距离更近的snake占据该点,并且在计算价值时加上上述规定的此点价值。
2)价值评估过程,首先将所有蛇的身体转化为在固定时间之后会消失的动态障碍物。详细见函数to_obtacle()
3)价值评估某一点值的确定,目前用的是1-2之间的勾股数,还有一个单位1。这个很难确定到底怎么最好,但是肯定跟几何是有关系的,数学直觉用了勾股数,看起来效果还不错,但是怎么解释我也不会(so良好的算法是无法解释的…)。
4)多种未采用的价值评估的想法,可以加上一个平方根倒数(用Fast Inverse Square Root可降低复杂度,保证算力),a,b是我方和对方的价值评估总和,
a
a
b
l
e
a_{able}
aable和
b
a
b
l
e
b_{able}
bable分别是双发可到达的地图上格点数目。比如:
(
a
−
b
+
c
1
a
1
∗
m
∗
n
−
∣
a
−
b
∣
)
(
a
+
b
+
c
2
a
2
∗
m
∗
n
−
∣
a
−
b
∣
)
\frac{(a-b+ \frac{c_1}{\sqrt{a_1*m*n-|a-b|}} )}{(a+b+ \frac{c_2}{\sqrt{a_2*m*n-|a-b|}} )}
(a+b+a2∗m∗n−∣a−b∣
c2)(a−b+a1∗m∗n−∣a−b∣
c1)根据真分数性质还有很多常识,各位请自行理解到底为啥这么干。
5)或者,加一个修正,即不仅仅按照某点的占据来看,还要看整个地图中,到底有多少点可以走(plus可达性)。
0.9
∗
(
a
−
b
)
a
+
b
+
0.1
∗
(
a
a
b
l
e
−
b
a
b
l
e
)
a
a
b
l
e
+
b
a
b
l
e
0.9*\frac{(a-b)}{a+b}+0.1*\frac{(a_{able}-b_{able})}{a_{able}+b_{able}}
0.9∗a+b(a−b)+0.1∗aable+bable(aable−bable)
1、毕竟是小组作业,可以认为,命名乱的地方,写的不简洁的地方都不是我写的,但是你也可以认为都是我写的(95++%嗯哼?)。
2、缺点:很明显的地方是,仅仅根据最短路就判断这个点是不是可以到达局限性太大了,虽然MCTS后续可以给你修正好一些,但是毕竟误差就是误差。
3、因为snake是同时决策的游戏,(贪吃蛇大作战的那种?)就所以我把它分成两层不符合逻辑,并且会造成十分复杂的数据结构,造成不太好扩展代码。
4、参数没法证明是收敛的,波动较大,继承对局之后可能出现不同的胜负情况。这可能是因为用了随机洗牌函数rand_shuffle,但是在计算了10万次之后参数仍不收敛确实是漏洞,参数没有调整好造成的抖振现象吧。
5、遗憾:有一些想法最后没加上去,因为没有思路该怎么加。比如,保证考虑了所有因素的话,一个点周围不仅仅有障碍物、蛇的身体,还应该区分蛇的身体到底是哪一方的,以及对应应该有不同的更复杂的估值。
价值评估关键代码:
int que[200]; int dis_vis[2][17][17]; double weight[2][17][17]; void to_obstacle(){ int k_temp=k; int xx,yy; int p=st0myfront(); //tmp_board_for_us[p>>4][p&0x0f]=11+k+(k-1)/2;//头消失的时间 for(int i=snaketmptail0;i<=snaketmphead0;i++){ while(k<=9||((k>9)&&((k-9)%3==0))) k++; p=snake0[i]; xx=p>>4,yy=p&0x0f; tmp_board_for_us[xx][yy]=k++; } k=k_temp; p=st1myfront(); //tmp_board_for_op[p>>4][p&0x0f]=11+k+(k-1)/2;//头消失的时间 for(int i=snaketmptail1;i<=snaketmphead1;i++){ while(k<=9||((k>9)&&((k-9)%3==0))) k++; p=snake1[i]; xx=p>>4,yy=p&0x0f; tmp_board_for_op[xx][yy]=k++; } return ; } void bfs(int which,int round) { int hh = 0; int tt = 0; int p; if(which) p=st1myfront(); else p=st0myfront(); que[tt++]=p; dis_vis[which][p>>4][p&0x0f]=0;//距离 while(tt!=hh) { int cur = que[hh++]; int x = cur>>4; int y = cur&0x0f; int vis_sum=0; for(int i=0; i<4; i++) { int xx = x+dx[i]; int yy = y+dy[i]; if(!inboard(xx,yy)) continue; if(dis_vis[which][xx][yy]!=INF){ vis_sum++; continue; } if(!board[xx][yy]){//在界内则试一试 int barrier=tmp_board_for_us[xx][yy]>tmp_board_for_op[xx][yy]?tmp_board_for_us[xx][yy]:tmp_board_for_op[xx][yy]; int temp_round=round+dis_vis[which][xx][yy];//能到达则试一试 if(temp_round>=barrier) { vis_sum++;//联通数目加一 que[tt++] = (xx<<4)+yy;//未访问过则加入 dis_vis[which][xx][yy] = dis_vis[which][x][y] + 1; }//最多多访问三次 } switch(vis_sum){ case 1:weight[which][x][y]=1.0;break; case 2:weight[which][x][y]=1.2;break; case 3:weight[which][x][y]=1.6;break; case 4:weight[which][x][y]=2.0;break; } } } return ; } double simulate_dis_fight() { for(int k=0; k<2; k++) { for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { dis_vis[k][i][j]=INF; } } } //outboard(); int k_temp=k; to_obstacle(); k=k_temp; bfs(0,k_temp); bfs(1,k_temp); double me=0; double op=0; for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { if(dis_vis[0][i][j]==INF&&dis_vis[1][i][j]==INF)continue; if(dis_vis[0][i][j]<dis_vis[1][i][j]) { me+=weight[0][i][j]; } if(dis_vis[0][i][j]>dis_vis[1][i][j]) { op+=weight[1][i][j]; } } } if(op-me==0) return 0.0; return (op-me)/(op+me); }
完整代码:
#pragma GCC optimize("O2") #pragma GCC optimize("O3") #pragma GCC optimize("Ofast,no-stack-protector") #pragma GCC optimize("unroll-loops") #include<bits/stdc++.h> #include"jsoncpp/json.h" using namespace std;//框架已经有了 const int MAX_NUM=1e6; const int INF=1e9; const int dx[4]= {-1, 0, 1, 0}; const int dy[4]= { 0, 1, 0,-1}; int tmp_board_for_us[17][17];//从某一个位置开始,向下走的时候,进行随机模拟 int tmp_board_for_op[17][17];//从某一个位置开始,向下走的时候,进行随机模拟 int count_num=0; struct point { int x,y; point(int _x,int _y) { x=_x; y=_y; } }; list<point> snake[2],snake_temp[2]; // 0表示自己的蛇,1表示对方的蛇 int snake0[400]; int snake1[400]; int snaketmp0[400]; int snaketmp1[400]; int snakehead0=-1; int snaketail0=0; int snakehead1=-1; int snaketail1=0; int snaketmphead0=-1; int snaketmptail0=0; int snaketmphead1=-1; int snaketmptail1=0; int board[17][17]; int k;//回合数 int n,m; inline vector<int> try_dir(int which); void outboard(); void outputSnakeBody(); inline int s1myfront() //返回头坐标 { return snake1[snakehead1]; } inline int s0myfront() //返回头坐标 { return snake0[snakehead0]; } inline int st1myfront() //返回头坐标 { return snaketmp1[snaketmphead1]; } inline int st0myfront() //返回头坐标 { return snaketmp0[snaketmphead0]; } inline int st0myback() //返回尾坐标 { return snaketmp0[snaketmptail0]; } inline int st1myback() //返回尾坐标 { return snaketmp1[snaketmptail1]; } inline void st1mypushfront(int loc){ snaketmphead1++; snaketmp1[snaketmphead1]=loc; } inline void st0mypushfront(int loc){ snaketmphead0++; snaketmp0[snaketmphead0]=loc; } class IO { public: inline void readJson() //读取输入 { memset(board,0,sizeof(board)); string str;//高度 string temp;//宽度 while(getline(cin,temp)) str+=temp; Json::Reader reader; Json::Value input; reader.parse(str,input); n=input["requests"][(Json::Value::UInt) 0]["height"].asInt(); //棋盘高度 m=input["requests"][(Json::Value::UInt) 0]["width"].asInt(); //棋盘宽度 int x=input["requests"][(Json::Value::UInt) 0]["x"].asInt(); //读蛇初始化的信息 if (x==1) { snake[0].push_front(point(1,1)); snake[1].push_front(point(n,m)); } else { snake[1].push_front(point(1,1)); snake[0].push_front(point(n,m)); } //处理地图中的障碍物 int obsCount=input["requests"][(Json::Value::UInt) 0]["obstacle"].size(); for (int i=0; i<obsCount; i++) { int ox=input["requests"][(Json::Value::UInt) 0]["obstacle"][(Json::Value::UInt) i]["x"].asInt(); int oy=input["requests"][(Json::Value::UInt) 0]["obstacle"][(Json::Value::UInt) i]["y"].asInt(); board[ox][oy]=1; } //蛇从出生点成长到当前局面状态 total=input["responses"].size(); int dire; for (int i=0; i<total; i++) { dire=input["responses"][i]["direction"].asInt(); move(0,dire,i); dire=input["requests"][i+1]["direction"].asInt(); move(1,dire,i); }// snake_init(); } void inline snake_init() { ///snake数组初始化 头指针初始化 for(list<point>::iterator iter=--snake[0].end(); iter!=--snake[0].begin(); --iter) { snakehead0++; snake0[snakehead0]=((iter->x)<<4)+iter->y; } for(list<point>::iterator iter=--snake[1].end(); iter!=--snake[1].begin(); --iter) { snakehead1++; snake1[snakehead1]=(iter->x<<4)+iter->y; } } void move(int id,int dire,int num) //编号为id的蛇朝向dire方向移动一步 { point p=*(snake[id].begin()); int x=p.x+dx[dire]; int y=p.y+dy[dire]; snake[id].push_front(point(x,y));//头插入法 if (!whetherGrow(num)) deleteEnd(id); } bool whetherGrow(int num) //本回合是否生长, 生长从0回合开始 生长则不删除尾巴 { if (num<=9) return true; if ((num-9)%3==0) return true; return false; } void deleteEnd(int id) //删去尾巴 { snake[id].pop_back(); } inline void writeJson(int dir) { Json::Value ret; ret["response"]["direction"]=dir;// ret["debug"]["count_num"]=count_num; int start=clock(); ret["debug"]["time"]=start; Json::FastWriter writer; cout<<writer.write(ret)<<endl; return; } int total;//回合数 }; class rand_maker { public: inline int rand_int(int l,int r){ return rand()%(r-l+1)+l; } inline void rand_shuffle(vector<int>::iterator starting,vector<int>::iterator ending)// ending 指向最后元素后一位? { int num=ending-starting; for(int i=num-1; i>=1; i--) { int j=rand_int(0,i-1); swap(*(starting+i),*(starting+j)); } return; } }; IO io; rand_maker r1; class MCTS { private: int total;//回合数 public: //我方对方棋盘 int board_for_us[17][17];//保存输入的我方位置信息 int board_for_op[17][17];//保存输入的对方位置信息 inline bool inboard(int x,int y) //inboard return true else return false { return x>=1 && x<=n && y>=1 && y<=m; } inline void init() //board_for_us board_for_op 1表示障碍物 2表示有蛇 { root=0; next_using=1; /// total=io.total; k=total; ///board_for_us初始化 for(int i=snaketail0;i<=snakehead0;i++) { board_for_us[snake0[i]>>4][snake0[i]&0x0f]=2; } for(int i=snaketail1;i<=snakehead1;i++) { board_for_op[snake1[i]>>4][snake1[i]&0x0f]=2; } snakeNode[0].which=1; ///把这个头通过list初始化 snakeNode[0].fa=-1; snakeNode[root].head0=s0myfront();//头 snakeNode[root].head1=s1myfront();//头 ///snaketmp初始化 for(int i=snaketail0;i<=snakehead0;i++) { snaketmphead0++; snaketmp0[snaketmphead0]=snake0[i]; } for(int i=snaketail1;i<=snakehead1;i++) { snaketmphead1++; snaketmp1[snaketmphead1]=snake1[i]; } for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { tmp_board_for_us[i][j]=board_for_us[i][j]; tmp_board_for_op[i][j]=board_for_op[i][j]; } } // outboard(); // outputSnakeBody(); snakeNode[root].init_data(); } /// int que[200]; int dis_vis[2][17][17]; double weight[2][17][17]; void to_obstacle(){ int k_temp=k; int xx,yy; int p=st0myfront(); //tmp_board_for_us[p>>4][p&0x0f]=11+k+(k-1)/2;//头消失的时间 for(int i=snaketmptail0;i<=snaketmphead0;i++){ while(k<=9||((k>9)&&((k-9)%3==0))) k++; p=snake0[i]; xx=p>>4,yy=p&0x0f; tmp_board_for_us[xx][yy]=k++; } k=k_temp; p=st1myfront(); //tmp_board_for_op[p>>4][p&0x0f]=11+k+(k-1)/2;//头消失的时间 for(int i=snaketmptail1;i<=snaketmphead1;i++){ while(k<=9||((k>9)&&((k-9)%3==0))) k++; p=snake1[i]; xx=p>>4,yy=p&0x0f; tmp_board_for_op[xx][yy]=k++; } return ; } void bfs(int which,int round) { int hh = 0; int tt = 0; int p; if(which) p=st1myfront(); else p=st0myfront(); que[tt++]=p; dis_vis[which][p>>4][p&0x0f]=0;//距离 while(tt!=hh) { int cur = que[hh++]; int x = cur>>4; int y = cur&0x0f; int vis_sum=0; for(int i=0; i<4; i++) { int xx = x+dx[i]; int yy = y+dy[i]; if(!inboard(xx,yy)) continue; if(dis_vis[which][xx][yy]!=INF){ vis_sum++; continue; } if(!board[xx][yy]){//在界内则试一试 int barrier=tmp_board_for_us[xx][yy]>tmp_board_for_op[xx][yy]?tmp_board_for_us[xx][yy]:tmp_board_for_op[xx][yy]; int temp_round=round+dis_vis[which][xx][yy];//能到达则试一试 if(temp_round>=barrier) { vis_sum++;//联通数目加一 que[tt++] = (xx<<4)+yy;//未访问过则加入 dis_vis[which][xx][yy] = dis_vis[which][x][y] + 1; }//最多多访问三次 } switch(vis_sum){ case 1:weight[which][x][y]=1.0;break; case 2:weight[which][x][y]=1.2;break; case 3:weight[which][x][y]=1.6;break; case 4:weight[which][x][y]=2.0;break; } } } return ; } double simulate_dis_fight() { for(int k=0; k<2; k++) { for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { dis_vis[k][i][j]=INF; } } } //outboard(); int k_temp=k; to_obstacle(); k=k_temp; bfs(0,k_temp); bfs(1,k_temp); double me=0; double op=0; for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { if(dis_vis[0][i][j]==INF&&dis_vis[1][i][j]==INF)continue; if(dis_vis[0][i][j]<dis_vis[1][i][j]) { me+=weight[0][i][j]; } if(dis_vis[0][i][j]>dis_vis[1][i][j]) { op+=weight[1][i][j]; } } } if(op-me==0) return 0.0; return (op-me)/(op+me); } inline void modify_board(int node,int k) //修改盘面 { if(tail_to_move(k)) { int p=st1myback(); tmp_board_for_op[p>>4][p&0x0f]=0; snaketmptail1++; p=st0myback(); tmp_board_for_us[p>>4][p&0x0f]=0; snaketmptail0++; } int x=snakeNode[node].head1>>4; int y=snakeNode[node].head1&0x0f; tmp_board_for_op[x][y]|=2; st1mypushfront((x<<4)+y); int fa=snakeNode[node].fa; x=snakeNode[fa].head0>>4; y=snakeNode[fa].head0&0x0f; tmp_board_for_us[x][y]|=2; st0mypushfront((x<<4)+y); return ; } inline bool tail_to_move(int num) //尾巴是否移动,回合数从0开始 { if (num<=9) return false; if ((num-9)%3==0) return false; return true; } inline int return_ans() //返回答案 { int endClock=int(0.99*double(CLOCKS_PER_SEC)); while(clock()<endClock) { UCT(root); } count_num=next_using; int ans=best_score_child(root,0); return snakeNode[ans].dir; }// private: class treeNode { public://进行先我后对方的顺序 int head0;//我方头的位置所在 int head1;//对方头的位置所在 int which;//0代表是我方,1代表是对方 int fa;//父节点 int intchild[4];//孩子节点 int intvachild[4];//备选节点 int child_p; int vachild_p; int maxChildNum;//最多合法孩子数目(对下一节点 int dir; double score;//总得分 int total;//模拟次数 inline void init_data() { child_p=-1; vachild_p=-1; vector<int> temp=try_dir((which+1)&1);//对子节点进行拓展 r1.rand_shuffle(temp.begin(),temp.end()); for(vector<int>::iterator it=temp.begin(); it!=temp.end(); it++) { vachild_p++; intvachild[vachild_p]=(*it); //孩子都放到里面 } maxChildNum=vachild_p+1; } }; treeNode snakeNode[MAX_NUM+5];//整个博弈树 int next_using;//下一个能用的空闲的点的坐标 int root=0; inline bool myempty(int node){ if(snakeNode[node].vachild_p<0) return true; else return false; } inline bool isEnd(int node) { return snakeNode[node].maxChildNum==0; //结束则返回1,否则返回0 } inline bool couldExpand(int node) { return !myempty(node); //空则不能扩展,否则可以拓展则返回1 } inline int expand(int node) //对node节点进行扩展 { //选child第一个元素作为扩展节点 扩展之前已经随机打乱过了 int dir=snakeNode[node].intvachild[snakeNode[node].vachild_p]; snakeNode[node].vachild_p--;//从有效孩子中删除 return newNode(node,dir);//返回新的节点 } inline int newNode(int fa,int dir) //创建新的节点 { int N=next_using++; snakeNode[N].fa=fa; snakeNode[N].dir=dir; snakeNode[N].which=(snakeNode[fa].which+1)&1; snakeNode[N].total=0; snakeNode[N].score=0; if(snakeNode[N].which==0) snakeNode[N].init_data(); int side=snakeNode[N].which; if(side) { int xx=(snakeNode[fa].head1>>4)+dx[dir],yy=(snakeNode[fa].head1&0x0f)+dy[dir]; snakeNode[N].head1=(xx<<4)+yy;//两个头都要修改 snakeNode[N].head0=snakeNode[fa].head0; }else{ int xx=(snakeNode[fa].head0>>4)+dx[dir],yy=(snakeNode[fa].head0&0x0f)+dy[dir]; snakeNode[N].head0=(xx<<4)+yy;//两个头都要修改 snakeNode[N].head1=snakeNode[fa].head1; } snakeNode[fa].child_p++; snakeNode[fa].intchild[snakeNode[fa].child_p]=N; return N; } //下述两个函数只需要判断最新走的那一步是否是冲突的,即只需要判断head inline bool if_we_die(int xx,int yy)//我方是否死亡 {//只需要判断头的位置 if(!board[xx][yy]&&!tmp_board_for_op[xx][yy]) return false; return true; } inline bool if_op_die(int xx,int yy) {//只需要判断头的位置 if(!board[xx][yy]&&!tmp_board_for_us[xx][yy]) return false; return true; } //对方是否死亡 inline bool if_continue(int node) { int xx=snakeNode[node].head0>>4; int yy=snakeNode[node].head0&0x0f; int flag_for_me=if_we_die(xx,yy); xx=snakeNode[node].head1>>4; yy=snakeNode[node].head1&0x0f; int flag_for_op=if_op_die(xx,yy); if(flag_for_me||flag_for_op) return false; else return true; } inline int calcScore(int node) { //返回对方得分 int fa=snakeNode[node].fa; int xx=snakeNode[fa].head0>>4; int yy=snakeNode[fa].head0&0x0f; int flag_for_me=if_we_die(xx,yy); xx=snakeNode[node].head1>>4; yy=snakeNode[node].head1&0x0f; int flag_for_op=if_op_die(xx,yy); if(flag_for_me&&flag_for_op) return 0;//同归于尽 if(flag_for_me) return 1;//我死了,对方获胜 else return -1;//对方死了,我获胜 }//计算当前局面的评分 inline int best_score_child(int node ,int c) //返回评分值最高的孩子节点的下标 { double mini=-1e9; int pos=0; for(int i=0;i<=snakeNode[node].child_p;i++) //遍历所有孩子找最满意的孩子 { int tmp=snakeNode[node].intchild[i];//孩子节点 double ucb=calcUcb(tmp,c); if(ucb>mini) { mini=ucb; pos=tmp; } } return pos;//将孩子的数组下标返回去 } inline double calcUcb(int node,int c) { treeNode t=snakeNode[node],fa=snakeNode[snakeNode[node].fa];//子节点,父节点 return (double)t.score/t.total*0.5+sqrt(c*log(fa.total)/t.total);//计算参数 } inline void UCT(int node) { for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { tmp_board_for_us[i][j]=board_for_us[i][j]; tmp_board_for_op[i][j]=board_for_op[i][j]; } } snaketmphead0=snakehead0; snaketmptail0=snaketail0; snaketmphead1=snakehead1; snaketmptail1=snaketail1; k=total;//回合数 while(isEnd(node)==0) { if(couldExpand(node)) { node=expand(node);//向下扩展节点 if(snakeNode[node].which==1) { modify_board(node,k); k++; if(snakeNode[node].maxChildNum==0) snakeNode[node].init_data(); if(if_continue(node)==0) snakeNode[node].maxChildNum=0;//如果分出了胜负,则不能继续拓展 break;//扩展到对方节点,则退出 } if(couldExpand(node)){ node=expand(node);//否则要再模拟一次,到达对方节点退出 modify_board(node,k); k++; if(snakeNode[node].maxChildNum==0) snakeNode[node].init_data(); if(if_continue(node)==0) snakeNode[node].maxChildNum=0;//如果分出了胜负,则不能继续拓展 break; } break; } node=best_score_child(node,1.8);//走最好的孩子 if(snakeNode[node].which==1){ modify_board(node,k); k++; if(snakeNode[node].maxChildNum==0) snakeNode[node].init_data(); } } double value=0; if(snakeNode[node].which==0){ value=1; } else if(isEnd(node)){//当前颜色是对方,并且我方已经无路可走 if(if_continue(node)==0){ value=calcScore(node);//已经分出了胜负,前方已经强行赋值为0 } else{ int num_op=try_dir(1).size();//这种情况是说,当前我方已经无路可走,则计算一下对方可以走多少,则当前的局数目应当加1 if(num_op==0) value=0;//若对方也无路可走,则平局 else value=1;//否则对方获胜 } } else value=simulate_dis_fight(); while(node>=0)//从尾巴向上 { snakeNode[node].total++; snakeNode[node].score+=value; value=-value; node=snakeNode[node].fa;//对方要获得相反的损失 } return; } }; MCTS mcts; inline vector<int> try_dir(int which) { int p; if(which) p=st1myfront(); else p=st0myfront(); int x=p>>4; int y=p&0x0f; vector<int> ans; for(int i=0; i<4; i++) { int xx=x+dx[i],yy=y+dy[i]; if(xx>=1 && xx<=n && yy>=1 && yy<=m) { int tail=st0myback(); if(tail==(xx<<4)+yy) if(!(k<=9||(k-9)%3==0))//修改了 加了取反 { ans.push_back(i); continue; } tail=st1myback(); if(tail==(xx<<4)+yy) if(!(k<=9||(k-9)%3==0))//修改了 加了取反 { ans.push_back(i); continue; } if(!board[xx][yy]&&!tmp_board_for_op[xx][yy]&&!tmp_board_for_us[xx][yy]) { ans.push_back(i); } } } return ans; } void outputSnakeBody() //调试语句 { for(int id=0;id<2;id++){ cout<<"snake_temp No."<<id<<endl; for (list<point>::iterator iter=snake_temp[id].begin();iter!=snake_temp[id].end();++iter) cout<<iter->x<<" "<<iter->y<<endl; cout<<endl; } } void outboard() { printf("this is board_for_us\n"); for(int j=1; j<=m; j++) { for(int i=1; i<=n;i++) printf("%d ",tmp_board_for_us[i][j]); cout<<endl; } cout<<endl<<endl; printf("this is board_for_op\n"); for(int j=1; j<=m; j++) { for(int i=1; i<=n; i++) printf("%d ",tmp_board_for_op[i][j]); cout<<endl; } cout<<endl<<endl; } int main() { //freopen("in.txt", "r", stdin); srand(time(0)); io.readJson(); mcts.init(); int dir=mcts.return_ans(); io.writeJson(dir); return 0; }
对于计算机博弈有了更深刻的理解吧,可惜在至今没有好好探索过博弈树,并且想好好学学α-β剪枝和PVS还有渴望搜索。 而且你好好跟别人交流的话,完全无私的话,更容易收获更多,反正我是这么想的。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。