botzone Tetris2

为了证明窝最近没有颓废

(并且为了多骗点访问量

游戏链接:https://botzone.org/game/Tetris2

大概就是先写个估价,然后剪剪枝搜它4步。

#include<iostream>
#include<string>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<cstring>
#define INF 1e180
using namespace std;
 
#define MAPWIDTH 10
#define MAPHEIGHT 20
 
//W1 防长条
//W2、W3 优先放两边 
//W4 forfuture
//W5、W6 封顶
//W7 多给长条 
//W8 maxheiht 
//W9、13 拒绝不可达行 
//W10 高度系数 
//W11 unreachable 
//W12 奖励行 
const int GO[7][4]={{1,1,1,1},{1,1,1,1},{1,1,0,0},{1,1,0,0},{1,1,1,1},{1,1,0,0},{1,0,0,0}};
const bool TYPEwork[7]={0,0,0,0,1,1,0};
const int M_DEEP=4,E_DEEP=2,RE=0,intwo=1;
double W1=1.2,W2=0.998,W3=0.98,W4=3,W5=1.4,W6=1,prize=0,W7=30,W8=10,W9=1,W10=100,W11=2,W12=intwo?100:0,W13=1.4,paper=5;
int Work_num=3,Type_num=3;
#define CONDITION (x==5&&y==3&&o==1)||(x==1&&y==2&&o==1)
// 我所在队伍的颜色(0为红,1为蓝,仅表示队伍,不分先后)
int currBotColor;
int enemyColor;
 
// 先y后x,记录地图状态,0为空,1为以前放置,2为刚刚放置,负数为越界
// (2用于在清行后将最后一步撤销再送给对方)
int gridInfo[2][MAPHEIGHT + 2][MAPWIDTH + 2] = { 0 };
 
// 代表分别向对方转移的行
int trans[2][6][MAPWIDTH + 2] = { 0 };
 
// 转移行数
int transCount[2] = { 0 };
 
// 运行eliminate后的当前高度
int maxHeight[2] = { 0 };
 
// 总消去行数的分数之和
int elimTotal[2] = { 0 };

// 连续几回合发生过消去了
int elimCombo[2] = { 0 };
 
// 一次性消去行数对应分数
const int elimBonus[] = { 0, 1, 3, 5, 7 };
 
// 给对应玩家的各类块的数目总计
int typeCountForColor[2][7] = { 0 };
int turnID, blockType;
int nextTypeForColor[2];
double MMH=0;
int debug;
#ifndef _BOTZONE_ONLINE
    FILE *DEBUG=fopen("b.out","w");
#endif
bool forsize[MAPHEIGHT+2][MAPWIDTH+2][4];
const int blockShape[7][4][8] = {
    { { 0,0,1,0,-1,0,-1,-1 },{ 0,0,0,1,0,-1,1,-1 },{ 0,0,-1,0,1,0,1,1 },{ 0,0,0,-1,0,1,-1,1 } },
    { { 0,0,-1,0,1,0,1,-1 },{ 0,0,0,-1,0,1,1,1 },{ 0,0,1,0,-1,0,-1,1 },{ 0,0,0,1,0,-1,-1,-1 } },
    { { 0,0,1,0,0,-1,-1,-1 },{ 0,0,0,1,1,0,1,-1 },{ 0,0,-1,0,0,1,1,1 },{ 0,0,0,-1,-1,0,-1,1 } },
    { { 0,0,-1,0,0,-1,1,-1 },{ 0,0,0,-1,1,0,1,1 },{ 0,0,1,0,0,1,-1,1 },{ 0,0,0,1,-1,0,-1,-1 } },
    { { 0,0,-1,0,0,1,1,0 },{ 0,0,0,-1,-1,0,0,1 },{ 0,0,1,0,0,-1,-1,0 },{ 0,0,0,1,1,0,0,-1 } },
    { { 0,0,0,-1,0,1,0,2 },{ 0,0,1,0,-1,0,-2,0 },{ 0,0,0,1,0,-1,0,-2 },{ 0,0,-1,0,1,0,2,0 } },
    { { 0,0,0,1,-1,0,-1,1 },{ 0,0,-1,0,0,-1,-1,-1 },{ 0,0,0,-1,1,-0,1,-1 },{ 0,0,1,0,0,1,1,1 } }
}; // 7种形状(长L| 短L| 反z| 正z| T| 直一| 田格),4种朝向(上左下右),8:每相邻的两个分别为x,y

const int rotateBlank[7][4][10] = {
    { { 1,1,0,0 },{ -1,1,0,0 },{ -1,-1,0,0 },{ 1,-1,0,0 } },
    { { -1,-1,0,0 },{ 1,-1,0,0 },{ 1,1,0,0 },{ -1,1,0,0 } },
    { { 1,1,0,0 },{ -1,1,0,0 },{ -1,-1,0,0 },{ 1,-1,0,0 } },
    { { -1,-1,0,0 },{ 1,-1,0,0 },{ 1,1,0,0 },{ -1,1,0,0 } },
    { { -1,-1,-1,1,1,1,0,0 },{ -1,-1,-1,1,1,-1,0,0 },{ -1,-1,1,1,1,-1,0,0 },{ -1,1,1,1,1,-1,0,0 } },
    { { 1,-1,-1,1,-2,1,-1,2,-2,2 } ,{ 1,1,-1,-1,-2,-1,-1,-2,-2,-2 } ,{ -1,1,1,-1,2,-1,1,-2,2,-2 } ,{ -1,-1,1,1,2,1,1,2,2,2 } },
    { { 0,0 },{ 0,0 } ,{ 0,0 } ,{ 0,0 } }
}; // 旋转的时候需要为空的块相对于旋转中心的坐标
 
class Tetris
{
public:
    const int blockType;   // 标记方块类型的序号 0~6
    int blockX;            // 旋转中心的x轴坐标
    int blockY;            // 旋转中心的y轴坐标
    int orientation;       // 标记方块的朝向 0~3
    const int(*shape)[8]; // 当前类型方块的形状定义
 
    int color;
 
    Tetris(int t, int color) : blockType(t), shape(blockShape[t]), color(color)
    { }
 
    inline Tetris &set(int x = -1, int y = -1, int o = -1)
    {
        blockX = x == -1 ? blockX : x;
        blockY = y == -1 ? blockY : y;
        orientation = o == -1 ? orientation : o;
        return *this;
    }
 
    // 判断当前位置是否合法
    inline bool isValid(int x = -1, int y = -1, int o = -1)
    {
        x = x == -1 ? blockX : x;
        y = y == -1 ? blockY : y;
        o = o == -1 ? orientation : o;
        if (o < 0 || o > 3)
            return false;
 
        int i, tmpX, tmpY;
        for (i = 0; i < 4; i++)
        {
            tmpX = x + shape[o][2 * i];
            tmpY = y + shape[o][2 * i + 1];
            if (tmpX < 1 || tmpX > MAPWIDTH ||
                tmpY < 1 || tmpY > MAPHEIGHT ||
                gridInfo[color][tmpY][tmpX] != 0)
                return false;
        }
        return true;
    }
 
    // 判断是否落地
    inline bool onGround()
    {
        if (isValid() && !isValid(-1, blockY - 1))
            return true;
        return false;
    }
 
    // 将方块放置在场地上
    inline bool place()
    {
        if (!onGround())
            return false;
 
        int i, tmpX, tmpY;
        for (i = 0; i < 4; i++)
        {
            tmpX = blockX + shape[orientation][2 * i];
            tmpY = blockY + shape[orientation][2 * i + 1];
            gridInfo[color][tmpY][tmpX] = 2;
        }
        return true;
    }
 
    // 检查能否逆时针旋转自己到o
    inline bool rotation(int o)
    {
        if (o < 0 || o > 3)
            return false;
 
        if (orientation == o)
            return true;
 
        int fromO = orientation;
        int i, blankX, blankY;
        while (true)
        {
            if (!isValid(-1, -1, fromO))
                return false;
 
            if (fromO == o)
                break;
                
            // 检查旋转碰撞
            if (intwo) for (i = 0; i < 5; i++) {
                blankX = blockX + rotateBlank[blockType][fromO][2 * i];
                blankY = blockY + rotateBlank[blockType][fromO][2 * i + 1];
                if (blankX == blockX && blankY == blockY)
                    break;
                if (gridInfo[color][blankY][blankX] != 0)
                    return false;
            }
 
            fromO = (fromO + 1) % 4;
        }
        return true;
    }
};
 
// 围一圈护城河
void init()
{
    int i;
    for (i = 0; i < MAPHEIGHT + 2; i++)
    {
        gridInfo[1][i][0] = gridInfo[1][i][MAPWIDTH + 1] = -2;
        gridInfo[0][i][0] = gridInfo[0][i][MAPWIDTH + 1] = -2;
    }
    for (i = 0; i < MAPWIDTH + 2; i++)
    {
        gridInfo[1][0][i] = gridInfo[1][MAPHEIGHT + 1][i] = -2;
        gridInfo[0][0][i] = gridInfo[0][MAPHEIGHT + 1][i] = -2;
    }
}
 
inline bool isValid(int map[MAPHEIGHT+2][MAPWIDTH+2],int type,int x,int y,int o){
    if (o < 0 || o > 3)    return false;
 
    int i, tmpX, tmpY;
    for (i = 0; i < 4; i++){
        tmpX = x + blockShape[type][o][2 * i];
        tmpY = y + blockShape[type][o][2 * i + 1];
        if (tmpX < 1 || tmpX > MAPWIDTH ||tmpY < 1 || tmpY > MAPHEIGHT ||map[tmpY][tmpX] != 0)return false;
    }
    return true;
}
inline bool onGround(int map[MAPHEIGHT+2][MAPWIDTH+2],int type,int x,int y,int o){
    if (isValid(map,type,x,y,o) && !isValid(map,type,x,y-1,o))
        return true;
    return false;
}
inline bool rotation(int map[MAPHEIGHT+2][MAPWIDTH+2],int type,int x,int y,int o){
    if (intwo) for (int i = 0; i < 5; i++) {
        int blankX = x + rotateBlank[type][o][2 * i];
        int blankY = y + rotateBlank[type][o][2 * i + 1];
        if (blankX == x && blankY == y) break;
        if (map[blankY][blankX])
        return 0;
    }
    return 1;
}
namespace Util
{
 
 
    // 检查能否从场地顶端直接落到当前位置
    inline bool checkDirectDropTo(int map[MAPHEIGHT+2][MAPWIDTH+2], int blockType, int x, int y, int o)
    {
        const int *def = blockShape[blockType][o];
        for (; y <= MAPHEIGHT; y++)
            for (int i = 0; i < 4; i++)
            {
                int _x = def[i * 2] + x, _y = def[i * 2 + 1] + y;
                if (_y > MAPHEIGHT)
                    continue;
                if (_y < 1 || _x < 1 || _x > MAPWIDTH || map[_y][_x])
                    return false;
            }
        return true;
    }
    void dfs(int map[MAPHEIGHT+2][MAPWIDTH+2],bool bo[MAPHEIGHT+2][MAPWIDTH+2][4],int type,int x,int y,int o){
        //cout<<x<<y<<o<<endl;
        if (!isValid(map,type,x,y,o)) return;
        if (bo[y][x][o]) return;
        //if (debug) fprintf(DEBUG,"O_O::::%d %d %d %d %d
",x,y,o,bo[y][x][o],sizeof(bo));
        bo[y][x][o]=1;
        dfs(map,bo,type,x-1,y,o);dfs(map,bo,type,x+1,y,o);dfs(map,bo,type,x,y-1,o);
        if (rotation(map,type,x,y,o))dfs(map,bo,type,x,y,(o+1)%4);
    }
    void init(int map[MAPHEIGHT+2][MAPWIDTH+2],bool bo[MAPHEIGHT+2][MAPWIDTH+2][4],int type,bool de=0){
        debug=de;
        memset(bo,0,sizeof(forsize));
        //if (debug) fprintf(DEBUG,"%d
",type);
        for (int o=0;o<4;o++)
        for (int x=1;x<=MAPWIDTH; x++){
            if (checkDirectDropTo(map,type,x,MAPHEIGHT,o)) dfs(map,bo,type,x,MAPHEIGHT,o);
            if (checkDirectDropTo(map,type,x,MAPHEIGHT-1,o)) dfs(map,bo,type,x,MAPHEIGHT-1,o);
            if (type==5) if (checkDirectDropTo(map,type,x,MAPHEIGHT-2,o)) dfs(map,bo,type,x,MAPHEIGHT-2,o);
        }
        
    }
    // 检查能否从场地顶端直接落到当前位置
    inline bool checkDirectDropTo(int color, int blockType, int x, int y, int o)
    {
        auto &def = blockShape[blockType][o];
        for (; y <= MAPHEIGHT; y++)
            for (int i = 0; i < 4; i++)
            {
                int _x = def[i * 2] + x, _y = def[i * 2 + 1] + y;
                if (_y > MAPHEIGHT)
                    continue;
                if (_y < 1 || _x < 1 || _x > MAPWIDTH || gridInfo[color][_y][_x])
                    return false;
            }
        return true;
    }
 
    // 消去行
    void eliminate(int color)
    {
        int &count = transCount[color] = 0;
        int i, j, emptyFlag, fullFlag, firstFull = 1, hasBonus = 0;
        maxHeight[color] = MAPHEIGHT;
        for (i = 1; i <= MAPHEIGHT; i++)
        {
            emptyFlag = 1;
            fullFlag = 1;
            for (j = 1; j <= MAPWIDTH; j++)
            {
                if (gridInfo[color][i][j] == 0)
                    fullFlag = 0;
                else
                    emptyFlag = 0;
            }
            if (fullFlag)
            {
                if (intwo&&firstFull && ++elimCombo[color] >= 3)
                {
                    // 奖励行
                    for (j = 1; j <= MAPWIDTH; j++)
                        trans[color][count][j] = gridInfo[color][i][j] == 1 ? 1 : 0;
                    count++;
                    hasBonus = 1;
                }
                firstFull = 0;
                for (j = 1; j <= MAPWIDTH; j++)
                {
                    // 注意这里只转移以前的块,不包括最后一次落下的块(“撤销最后一步”)
                    trans[color][count][j] = gridInfo[color][i][j] == 1 ? 1 : 0;
                    gridInfo[color][i][j] = 0;
                }
                count++;
            }
            else if (emptyFlag)
            {
                maxHeight[color] = i - 1;
                break;
            }
            else
                for (j = 1; j <= MAPWIDTH; j++)
                {
                    gridInfo[color][i - count + hasBonus][j] =
                        gridInfo[color][i][j] > 0 ? 1 : gridInfo[color][i][j];
                    if (count)
                        gridInfo[color][i][j] = 0;
                }
        }
        if (count == 0)
            elimCombo[color] = 0;
        maxHeight[color] -= count - hasBonus;
        elimTotal[color] += elimBonus[count];
    }
 
    // 转移双方消去的行,返回-1表示继续,否则返回输者
    int transfer()
    {
        int color1 = 0, color2 = 1;
        if (transCount[color1] == 0 && transCount[color2] == 0)
            return -1;
        if (transCount[color1] == 0 || transCount[color2] == 0)
        {
            if (transCount[color1] == 0 && transCount[color2] > 0)
                swap(color1, color2);
            int h2;
            maxHeight[color2] = h2 = maxHeight[color2] + transCount[color1];
            if (h2 > MAPHEIGHT)
                return color2;
            int i, j;
 
            for (i = h2; i > transCount[color1]; i--)
                for (j = 1; j <= MAPWIDTH; j++)
                    gridInfo[color2][i][j] = gridInfo[color2][i - transCount[color1]][j];
 
            for (i = transCount[color1]; i > 0; i--)
                for (j = 1; j <= MAPWIDTH; j++)
                    gridInfo[color2][i][j] = trans[color1][i - 1][j];
            return -1;
        }
        else
        {
            int h1, h2;
            maxHeight[color1] = h1 = maxHeight[color1] + transCount[color2];//从color1处移动count1去color2
            maxHeight[color2] = h2 = maxHeight[color2] + transCount[color1];
 
            if (h1 > MAPHEIGHT) return color1;
            if (h2 > MAPHEIGHT) return color2;
 
            int i, j;
            for (i = h2; i > transCount[color1]; i--)
                for (j = 1; j <= MAPWIDTH; j++)
                    gridInfo[color2][i][j] = gridInfo[color2][i - transCount[color1]][j];
 
            for (i = transCount[color1]; i > 0; i--)
                for (j = 1; j <= MAPWIDTH; j++)
                    gridInfo[color2][i][j] = trans[color1][i - 1][j];
 
            for (i = h1; i > transCount[color2]; i--)
                for (j = 1; j <= MAPWIDTH; j++)
                    gridInfo[color1][i][j] = gridInfo[color1][i - transCount[color2]][j];
 
            for (i = transCount[color2]; i > 0; i--)
                for (j = 1; j <= MAPWIDTH; j++)
                    gridInfo[color1][i][j] = trans[color2][i - 1][j];
 
            return -1;
        }
    }
 
    // 颜色方还能否继续游戏
    inline bool canPut(int color, int blockType)
    {
        Tetris t(blockType, color);
        for (int y = MAPHEIGHT; y >= 1; y--)
            for (int x = 1; x <= MAPWIDTH; x++)
                for (int o = 0; o < 4; o++)
                {
                    t.set(x, y, o);
                    if (t.isValid() && checkDirectDropTo(color, blockType, x, y, o))
                        return true;
                }
        return false;
    }
 
    // 打印场地用于调试
    inline void printField()
    {
#ifndef _BOTZONE_ONLINE
        static const char *i2s[] = {
            "~~",
            "~~",
            "  ",
            "[]",
            "##"
        };
        cout << "~~:墙,[]:块,##:新块" << endl;
        for (int y = MAPHEIGHT + 1; y >= 0; y--)
        {
            for (int x = 0; x <= MAPWIDTH + 1; x++)
                cout << i2s[gridInfo[0][y][x] + 2];
            for (int x = 0; x <= MAPWIDTH + 1; x++)
                cout << i2s[gridInfo[1][y][x] + 2];
            cout << endl;
        }
#endif
    }
}
int sum_n[21]={0,1,3,6,10,15,21,28,36,45,55,66,78,91,105,120,136,153,171,190,210};
double GetBoardTransitions(int map[MAPHEIGHT+2][MAPWIDTH+2]){
    int mmh=0;
    
    for (int _y=1;_y<=MAPHEIGHT;_y++)
    for (int _x=1;_x<MAPWIDTH;_x++)
    if ((map[_y][_x]&&!map[_y][_x+1])||(!map[_y][_x]&&map[_y][_x+1])) mmh++;
    
    
    for (int _y=1;_y<MAPHEIGHT;_y++)
    for (int _x=1;_x<=MAPWIDTH;_x++)
    if ((map[_y][_x]&&!map[_y+1][_x])||(!map[_y][_x]&&map[_y+1][_x])) mmh++;
    
    return mmh;
}
double GetBoardBuriedHoles(int map[MAPHEIGHT+2][MAPWIDTH+2]){
    int mmh=0;
    
    for (int _x=1;_x<=MAPWIDTH;_x++){
        int _y;
        for (_y=MAPHEIGHT;_y;_y--) if (map[_y][_x]) break;
        for (;_y;_y--) if (!map[_y][_x]) mmh++;
    }
    
    return mmh;
}
double GetBoardWells(int map[MAPHEIGHT+2][MAPWIDTH+2]){
    double mmh=0,W;
    
    for (int _x=1;_x<=MAPWIDTH;_x++){
        int _y,wells=0,f=0;W=1.5;
        for (_y=MAPHEIGHT;_y>=0;_y--){
            if(map[_y][_x]==0){
                if(map[_y][_x-1]!=0&&map[_y][_x+1]!=0) wells++;
            }else{
                mmh+=sum_n[wells]*W;
                wells=0;
                if (f) W+=0.1;else W=0.8;
                f=1;
            }
        }
    }
    
    return mmh;
}
int qx[300],qy[300],l,r;
const int f[2][4]={{0,0,1,-1},{1,-1,0,0}};
inline int bfs(int map[MAPHEIGHT+2][MAPWIDTH+2]){
    l=r=0;
    bool bo[MAPHEIGHT+2][MAPWIDTH+2];
    for (int _x=1;_x<=MAPWIDTH;_x++)
    for (int _y=1;_y<=MAPHEIGHT;_y++) bo[_y][_x]=0;
    
    for (int _x=1;_x<=MAPWIDTH;_x++) if (!map[MAPHEIGHT][_x]) qx[r]=_x,qy[r]=MAPHEIGHT,r++;
    while (l<r){
        for (int i=0;i<4;i++)
        if (!map[qy[l]+f[0][i]][qx[l]+f[1][i]]&&!bo[qy[l]+f[0][i]][qx[l]+f[1][i]])
        bo[qy[l]+f[0][i]][qx[l]+f[1][i]]=1,qy[r]=qy[l]+f[0][i],qx[r]=qx[l]+f[1][i],r++;
        l++;
    }
    double mmh=0;
    for (int _x=1;_x<=MAPWIDTH;_x++)
    for (int _y=1;_y<=MAPHEIGHT;_y++)
    mmh+=(!map[_y][_x])&&(!bo[_y][_x]);
    
    return mmh;
}
int finalX, finalY, finalO,_finalX,_finalY,_finalO;
double work(int _map[MAPHEIGHT+2][MAPWIDTH+2],int ty,int deepth,double forfuture,bool currBotColor,int eRound);
bool canreach[7][MAPHEIGHT+2][MAPWIDTH+2];
double Mavis(int _map[MAPHEIGHT+2][MAPWIDTH+2],int type,int x,int y,int o,int deepth,double MMH,bool currBotColor,int eRound){
    bool _bo[MAPHEIGHT+2][MAPWIDTH+2][4],cell_reach[MAPHEIGHT+2][MAPWIDTH+2];
    int map[MAPHEIGHT+2][MAPWIDTH+2];
    int emptynum[MAPHEIGHT+2],sta[MAPHEIGHT+2];
    bool reach[MAPHEIGHT+2];
    double value[MAPHEIGHT+2][MAPWIDTH+2];
    memset(emptynum,0,sizeof(emptynum));
    memset(sta,0,sizeof(sta));
    memset(reach,1,sizeof(reach));
    memset(cell_reach,0,sizeof(cell_reach));
    for (int _y=0;_y<=MAPHEIGHT+1;_y++)
    for (int _x=0;_x<=MAPWIDTH+1;_x++) map[_y][_x]=_map[_y][_x];
    double holenum=1+prize*10;
    int ErodedPieceCellsMetric,erodedShape=0;
    
    
    bool myCount[7]={0,0,0,0,0,0,0};
    for (int i=0;i<7;i++){
        myCount[i]=1;
        for (int j=0;j<7;j++)
        if (i!=j&&typeCountForColor[currBotColor][i]+1-typeCountForColor[currBotColor][j]>2) myCount[i]=0;
    }
    for (int i=0;i<4;i++){
        int tmpX=x+blockShape[type][o][2*i];
        int tmpY=y+blockShape[type][o][2*i+1];
        map[tmpY][tmpX]=3;
    }
    
    
    int pop=0,O_O=0;
    for (int _y=1;_y<=MAPHEIGHT;_y++){
        int _x=1;
        for (_x=1;_x<=MAPWIDTH;_x++)
        if (!map[_y][_x]) break;
        if (_x==MAPWIDTH+1){
            holenum-=prize;pop++;
            for (_x=1;_x<=MAPWIDTH;_x++) erodedShape+=map[_y][_x]==3,map[_y][_x]=-1;
        }
    }
    ErodedPieceCellsMetric=pop*erodedShape;
    for (int _x=1;_x<=MAPWIDTH;_x++){
        int p=1;
        for (int i=1;i<=MAPHEIGHT;i++)
        if (map[i][_x]!=-1) map[p][_x]=map[i][_x],p++;
        for (;p<=MAPHEIGHT;p++) map[p][_x]=0;
    }
    
    double P_P=0;
    int max=0;
    for (int _x=1;_x<=MAPWIDTH;_x++){
        int _y=MAPHEIGHT;
        for (;_y;_y--) if (map[_y][_x]) break;
        double cost=_y*_y;
        int u=x<6?x:x-5;
        cost*=pow(1.05,u);
        P_P+=cost;
        if (max<_y) max=_y;
    }
    int BoardTransitions=GetBoardTransitions(map),BuriedHoles=GetBoardBuriedHoles(map),Wells=GetBoardWells(map),Bfs=bfs(map);
    
    holenum=sqrt(P_P)/3+2.5*max+2*BoardTransitions+7*BuriedHoles+2*Bfs+Wells;
    
    if (pop&&eRound>1) holenum-=W12;
    
#ifndef _BOTZONE_ONLINE
    if (CONDITION) fprintf(DEBUG,">_<%d %d %d %d
",x,y,o,deepth);
    if (CONDITION){
        for (int y=MAPHEIGHT;y;y--,fprintf(DEBUG,"
"))
        for (int x=1;x<=MAPWIDTH;x++)
        fprintf(DEBUG,"%c",map[y][x]?'#':'.');
        fprintf(DEBUG,"%d %d %d %d %d %lf
",x,y,o,deepth,type,holenum);
        fprintf(DEBUG,"ErodedPieceCellsMetric:%d
",ErodedPieceCellsMetric);
        fprintf(DEBUG,"BoardTransitions:%d
",BoardTransitions);
        fprintf(DEBUG,"BuriedHoles:%d
",BuriedHoles);
        fprintf(DEBUG,"Wells:%d

",Wells);
    }
#endif
    //printf("%d %d %d %d
",x,y,o,deepth);
    if (deepth){
        if (deepth==1){
            double forfuture=-INF,test;
            for (int i=0;i<7;i++)
            if (myCount[i]){
                typeCountForColor[currBotColor][i]++;
                if ((test=work(map,i,deepth-1,forfuture,currBotColor,pop?eRound+1:0))>forfuture) forfuture=test;
                typeCountForColor[currBotColor][i]--;
            }
            if (forfuture>=INF-1) return INF-1;
            holenum+=forfuture*W4;
            //printf("%d %d %d %lf %lf
",x,y,o,holenum,forfuture);
        }else{
            int type_num=Type_num;
            int TY[type_num];
            double Work[type_num];
            double forfuture=-INF,test;
            for (int j=0;j<type_num;j++) Work[j]=-INF;
            for (int i=0,j;i<7;i++)
            if (myCount[i]){
                typeCountForColor[currBotColor][i]++;
                
                test=work(map,i,0,forfuture,currBotColor,pop?eRound+1:0);
                for (j=0;j<type_num;j++) if (Work[j]<test) break;
                if (j<type_num){
                    for (int k=type_num-1;k>j;k--) TY[k]=TY[k-1],Work[k]=Work[k-1];
                    Work[j]=test;TY[j]=i;
                }
                
                typeCountForColor[currBotColor][i]--;
            }
            
            
            for (int i=0;i<type_num;i++)
            if (Work[i]>-INF+1){
                if (Work[0]<0){
                    if (Work[i]<Work[0]*1.05-1) break;
                }else if (Work[i]<Work[0]*0.95-1) break;
                typeCountForColor[currBotColor][TY[i]]++;
                if ((test=work(map,TY[i],deepth-1,forfuture,currBotColor,pop?eRound+1:0))>forfuture) forfuture=test;
                typeCountForColor[currBotColor][TY[i]]--;
            }
            /*printf("%d
",type_num);
            for (int i=0;i<type_num;i++) printf("%lf ",Work[i]);puts("");
            */
            if (forfuture>=INF-1) return INF-1;
            holenum+=forfuture*W4;
            //printf("%d %d %d %lf %lf
",x,y,o,holenum,forfuture);
        }
    }
    holenum-=ErodedPieceCellsMetric;
    
    return holenum;
}
double work(int _map[MAPHEIGHT+2][MAPWIDTH+2],int ty,int deepth,double forfuture,bool currBotColor,int eRound){
    bool bo[MAPHEIGHT+2][MAPWIDTH+2][4];
    int fx=-1,fy,fo,i,work_num=Work_num;
    /*fprintf(DEBUG,">_<%d
",ty);
    for (int y=MAPHEIGHT;y;y--,fprintf(DEBUG,"
"))
    for (int x=1;x<=MAPWIDTH;x++)
    fprintf(DEBUG,"%c",_map[y][x]?'#':'.');*/
    double MMH=INF,test;
    Util::init(_map,bo,ty);
    if (deepth){
        double work[work_num];
        int XX[work_num],YY[work_num],OO[work_num];
        for (i=0;i<work_num;i++) work[i]=INF;
        for (int y = 1; y <= MAPHEIGHT; y++)
        for (int x = 1; x <= MAPWIDTH; x++)
        for (int o = 0; o < 4; o++)
        if (GO[ty][o]&&onGround(_map,ty,x,y,o)&&bo[y][x][o]){
            test=Mavis(_map,ty,x,y,o,0,MMH,currBotColor,eRound);
            for (i=0;i<work_num;i++) if (test<work[i]) break;
            if (i==work_num) continue;
            for (int j=work_num-1;j>i;j--) work[j]=work[j-1],XX[j]=XX[j-1],YY[j]=YY[j-1],OO[j]=OO[j-1];
            work[i]=test;XX[i]=x;YY[i]=y;OO[i]=o;
        }
        for (int i=0;i<work_num;i++)
        if (work[i]<INF-1){
            if (work[0]<0){
                if (work[i]>work[0]*0.8+10) break;
            }else if (work[i]>work[0]*1.2+10) break;
            if ((test=Mavis(_map,ty,XX[i],YY[i],OO[i],deepth,MMH,currBotColor,eRound))<MMH){
                fx=XX[i];fy=YY[i];fo=OO[i];
                MMH=test;
                if (MMH<forfuture) return MMH;
            }
        }
        if (fx==-1) fx=XX[0],fy=YY[0],fo=OO[0];
    }else{
        for (int y = 1; y <= MAPHEIGHT; y++)
        for (int x = 1; x <= MAPWIDTH; x++)
        for (int o = 0; o < 4; o++)
        if (GO[ty][o]&&onGround(_map,ty,x,y,o)&&bo[y][x][o]&&(test=Mavis(_map,ty,x,y,o,0,INF,currBotColor,eRound))<MMH){
            fx=x;
            fy=y;
            fo=o;
            MMH=test;
            if (MMH<forfuture) return MMH;
        }
    }
    finalX=fx;finalY=fy;finalO=fo;
    //printf("%d %d %d %d %d
",ty,deepth,fx,fy,fo);
    //fprintf(DEBUG,"===================================%d %d %d %d %lf
",ty,finalX,finalY,finalO,MMH);
    return MMH;
}
double gain(int _map[MAPHEIGHT+2][MAPWIDTH+2],int x,int y,int o,int ty,int _ty,bool currBotColor,int DEEPTH){
    int map[MAPHEIGHT+2][MAPWIDTH+2];
    for (int _y=0;_y<=MAPHEIGHT+1;_y++)
    for (int _x=0;_x<=MAPWIDTH+1;_x++) map[_y][_x]=_map[_y][_x];
    for (int i=0;i<4;i++){
        int tmpX=x+blockShape[ty][o][2*i];
        int tmpY=y+blockShape[ty][o][2*i+1];
        map[tmpY][tmpX]=3;
    }
    
    
    int pop=0;
    for (int _y=1;_y<=MAPHEIGHT;_y++){
        int _x=1;
        for (_x=1;_x<=MAPWIDTH;_x++)
        if (!map[_y][_x]) break;
        if (_x==MAPWIDTH+1){
            pop++;
            for (_x=1;_x<=MAPWIDTH;_x++) map[_y][_x]=-1;
        }
    }
    for (int _x=1;_x<=MAPWIDTH;_x++){
        int p=1;
        for (int i=1;i<=MAPHEIGHT;i++)
        if (map[i][_x]!=-1) map[p][_x]=map[i][_x],p++;
        for (;p<=MAPHEIGHT;p++) map[p][_x]=0;
    }
    
    return work(map,_ty,DEEPTH,INF,currBotColor,pop?elimCombo[currBotColor]+1:0);
}
int blockForEnemy(int _map[MAPHEIGHT+2][MAPWIDTH+2],int ty,int DEEPTH){
    int minCount = 99,mmh=-1;
    for (int i = 0; i < 7; i++)
    if (typeCountForColor[enemyColor][i] < minCount) minCount = typeCountForColor[enemyColor][i];
    
    bool bo[MAPHEIGHT+2][MAPWIDTH+2][4];
    int fx=-1,fy,fo,i,work_num=Work_num;
        double MMH=INF,test;
        Util::init(_map,bo,ty);
        double work[work_num];
        int XX[work_num],YY[work_num],OO[work_num];
        for (i=0;i<work_num;i++) work[i]=INF;
        for (int y = 1; y <= MAPHEIGHT; y++)
        for (int x = 1; x <= MAPWIDTH; x++)
        for (int o = 0; o < 4; o++)
        if (onGround(_map,ty,x,y,o)&&bo[y][x][o]){
            test=Mavis(_map,ty,x,y,o,0,MMH,currBotColor,elimCombo[currBotColor]);
            for (i=0;i<work_num;i++) if (test<work[i]) break;
            if (i==work_num) continue;
            for (int j=work_num-1;j>i;j--) work[j]=work[j-1],XX[j]=XX[j-1],YY[j]=YY[j-1],OO[j]=OO[j-1];
            work[i]=test;XX[i]=x;YY[i]=y;OO[i]=o;
        }
    
    double _mmh=-INF;
    for (int _ty=0;_ty<7;_ty++)
    if (typeCountForColor[enemyColor][_ty]+1-minCount<=2){
        typeCountForColor[enemyColor][_ty]++;
        double _MMH=INF;
        for (int i=0;i<work_num;i++)
        if (work[i]<INF-1){
            if (work[0]<0){
                if (work[i]>work[0]*0.8+10) break;
            }else if (work[i]>work[0]*1.2+10) break;
            if ((test=gain(_map,XX[i],YY[i],OO[i],ty,_ty,enemyColor,DEEPTH))<_MMH){
                _MMH=test;
                //printf("===%d %lf
",i,test);
            }
        }
        
        if (_MMH>_mmh) _mmh=_MMH,mmh=_ty;
        
        //printf("%d %lf
",_ty,_MMH);
        typeCountForColor[enemyColor][_ty]--;
    }
    return mmh;
}
int main(){
#ifndef _BOTZONE_ONLINE
    freopen("a.in","r",stdin);
    //freopen("a.out","w",stdout);
#endif
    // 加速输入
    istream::sync_with_stdio(false);
    srand(time(NULL));
    init();
 
    cin >> turnID;
 
    // 先读入第一回合,得到自己的颜色
    // 双方的第一块肯定是一样的
    cin >> blockType >> currBotColor;
    enemyColor = 1 - currBotColor;
    nextTypeForColor[0] = blockType;
    nextTypeForColor[1] = blockType;
    typeCountForColor[0][blockType]++;
    typeCountForColor[1][blockType]++;
 
    // 然后分析以前每回合的输入输出,并恢复状态
    // 循环中,color 表示当前这一行是 color 的行为
    // 平台保证所有输入都是合法输入
    for (int i = 1; i < turnID; i++){
        int currTypeForColor[2] = { nextTypeForColor[0], nextTypeForColor[1] };
        int x, y, o;
        // 根据这些输入输出逐渐恢复状态到当前回合
 
        // 先读自己的输出,也就是自己的行为
        // 自己的输出是自己的最后一步
        // 然后模拟最后一步放置块
        cin >> blockType >> x >> y >> o;
 
        // 我当时把上一块落到了 x y o!
        Tetris myBlock(currTypeForColor[currBotColor], currBotColor);
        myBlock.set(x, y, o).place();
 
        // 我给对方什么块来着?
        typeCountForColor[enemyColor][blockType]++;
        nextTypeForColor[enemyColor] = blockType;
 
        // 然后读自己的输入,也就是对方的行为
        // 裁判给自己的输入是对方的最后一步
        cin >> blockType >> x >> y >> o;
 
        // 对方当时把上一块落到了 x y o!
        Tetris enemyBlock(currTypeForColor[enemyColor], enemyColor);
        enemyBlock.set(x, y, o).place();
 
        // 对方给我什么块来着?
        typeCountForColor[currBotColor][blockType]++;
        nextTypeForColor[currBotColor] = blockType;
 
        // 检查消去
        Util::eliminate(0);
        Util::eliminate(1);
 
        // 进行转移
        Util::transfer();
    }
    
 
 
 
    // 做出决策(你只需修改以下部分)
    // 遇事不决先输出(平台上编译不会输出)
    work(gridInfo[currBotColor],blockType,M_DEEP,-INF,currBotColor,elimCombo[currBotColor]);
    _finalX=finalX;_finalY=finalY;_finalO=finalO;
    
        int currTypeForColor[2] = { nextTypeForColor[0], nextTypeForColor[1] };
        Tetris myBlock(currTypeForColor[currBotColor], currBotColor);
        myBlock.set(_finalX,_finalY,_finalO).place();
#ifndef _BOTZONE_ONLINE
        Util::printField();
#endif
    /*work(gridInfo[enemyColor],nextTypeForColor[enemyColor],1,-INF);
    
 
 
        Tetris enemyBlock(currTypeForColor[enemyColor], enemyColor);
        enemyBlock.set(finalX,finalY,finalO).place();
    //Util::printField();
        
        Util::eliminate(0);
        Util::eliminate(1);
        Util::transfer();
    */
    cout << blockForEnemy(gridInfo[enemyColor],nextTypeForColor[enemyColor],E_DEEP)<< " " << _finalX << " " << _finalY << " " << _finalO<<endl;
}
View Code
原文地址:https://www.cnblogs.com/Enceladus/p/7909638.html