HDU5374 Tetris (2015年多校比赛第7场)大模拟

思路:

先写好了几个函数。旋转,四种操作,判断是否可以进行合并消除

题中有好几处要考虑的细节问题,如

自然下落到底部时不进行合并的判断,而是当自然下落非法时才判断

如果消除一行,这一行上面的所以方块只会下落一行,不存在直接下落到底部的情况

比赛时题意没有理解好,错了这两个地方。。

还有一些写法上的错误,这种左右移动的题目坐标还是要从1开始,方便许多

左右移动,如果非法要复原的时候,复原的操作要与移动操作 完全相反,并且这个范围要从0开始,因为移动的时候可能移动到非法的位置。

赛后看了标程,各种优美简洁的代码。模拟能力还有待加强。

#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<cstdio>
#include<vector>
#define pb push_back
#define debug puts("=====================");
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
typedef long long ll;
int t;
int Map[20][20];     //记录整体
int updata[20][20];  //记录当前掉落方块
char ch[1111];
int a[1111];
int n;
int chong()        //判断是否有非法操作
{
    int sum = 0;
    for(int i=1; i<=12; i++)
        for(int j=1; j<=9; j++)
            if(updata[i][j]) sum++;
    if(sum!=4)
        return 0;
    for(int i=1; i<=12; i++)
        for(int j=1; j<=9; j++)
            if(updata[i][j]+Map[i][j]>1)
                return 0;
    return 1;
}
int zhuan(int type,int x,int y)  //旋转
{
    if(type==1)
    {
        swap(updata[x-1][y],updata[x][y+1]);
        swap(updata[x-2][y],updata[x][y+2]);
        swap(updata[x-3][y],updata[x][y+3]);
        if(!chong())                          //如果非法,再转回来
        {
            swap(updata[x-1][y],updata[x][y+1]);
            swap(updata[x-2][y],updata[x][y+2]);
            swap(updata[x-3][y],updata[x][y+3]);
        }
    }
    else if(type==2)
    {
        if(updata[x][y]==0)   ///3->4
        {
            swap(updata[x-1][y],updata[x-2][y+1]);
            swap(updata[x-1][y+2],updata[x][y+1]);
            swap(updata[x][y+2],updata[x][y]);
            if(!chong())
            {
                swap(updata[x-1][y],updata[x-2][y+1]);
                swap(updata[x-1][y+2],updata[x][y+1]);
                swap(updata[x][y+2],updata[x][y]);
            }
        }
        else
        {
            if(updata[x-1][y]&&updata[x][y+1]) ///1->2
            {
                swap(updata[x][y+1],updata[x-2][y]);
                swap(updata[x][y+2],updata[x-2][y+1]);
                if(!chong())
                {
                    swap(updata[x][y+1],updata[x-2][y]);
                    swap(updata[x][y+2],updata[x-2][y+1]);
                }
            }
            else if(updata[x-1][y]&&!updata[x][y+1]) ///2->3
            {
                swap(updata[x][y],updata[x-1][y+1]);
                swap(updata[x-2][y],updata[x-1][y+2]);
                swap(updata[x-2][y+1],updata[x][y+2]);
                if(!chong())
                {
                    swap(updata[x][y],updata[x-1][y+1]);
                    swap(updata[x-2][y],updata[x-1][y+2]);
                    swap(updata[x-2][y+1],updata[x][y+2]);
                }
            }
            else if(!updata[x-1][y]&&updata[x][y+1]) ///4->1
            {
                swap(updata[x-1][y+1],updata[x-1][y]);
                swap(updata[x-2][y+1],updata[x][y+2]);
                if(!chong())
                {
                    swap(updata[x-1][y+1],updata[x-1][y]);
                    swap(updata[x-2][y+1],updata[x][y+2]);
                }
            }
        }
    }
}
int  ctrl(char lei,int type)    //控制上下左右
{
    if(lei=='w')
    {
        if(type==0)
            return 0;
        int xx,yy;
        xx = -9999;
        yy = 9999;
        for(int i=1; i<=12; i++)
            for(int j=1; j<=9; j++)
                if(updata[i][j])
                    xx = max(xx,i),yy = min(yy,j);   //找到绿色的点,以这个点为基准
        zhuan(type,xx,yy);
    }
    else if(lei=='a')
    {
        for(int i=1; i<=12; i++)
            for(int j=0; j<=10; j++)
                if(updata[i][j]) swap(updata[i][j],updata[i][j-1]);
        if(!chong())                                //如果非法,再移回来
        {
            for(int i=1; i<=12; i++)
                for(int j=10; j>=0; j--)
                    if(updata[i][j]) swap(updata[i][j],updata[i][j+1]);
        }
    }
    else if(lei=='d')
    {
        for(int i=1; i<=12; i++)
            for(int j=10; j>=0; j--)
                if(updata[i][j])  swap(updata[i][j],updata[i][j+1]);
        if(!chong())
        {
            for(int i=1; i<=12; i++)
                for(int j=0; j<=10; j++)
                    if(updata[i][j])  swap(updata[i][j],updata[i][j-1]);
        }
    }
    else if(lei=='s')
    {

        for(int i=13; i>=1; i--)
            for(int j=1; j<=9; j++)
                if(updata[i][j]) swap(updata[i][j],updata[i+1][j]);
        if(!chong())
        {
            for(int i=1; i<=13; i++)
                for(int j=1; j<=9; j++)
                    if(updata[i][j]) swap(updata[i][j],updata[i-1][j]);
        }
    }
    return 1;
}
int score,tmp,jj,len;
int di()            //判断是否可以合并、消除
{
    int go = 1;
    for(int i=1; i<=11; i++)
        for(int j=1; j<=9; j++)
        {
            if(updata[i][j]&&updata[i+1][j]==0)
            {
                if(Map[i+1][j])
                    go = 0;
            }
        }
    for(int j=1; j<=9; j++)
    {
        if(updata[12][j])
            go = 0;
    }
    if(go)
        return 0;
    for(int i=1; i<=12; i++)
        for(int j=1; j<=9; j++)
        {
            if(updata[i][j])
                Map[i][j]  = updata[i][j];
        }
    while(1)
    {
        int flag = 0;
        int hang = 12;
        for(int i=1; i<=12; i++)
        {
            int sum = 0;
            if(Map[i][1])
            {
                for(int j=1; j<=9; j++)
                    sum+=Map[i][j];
            }
            if(sum==9)
            {
              //  cout<<"--------\n";
                hang = i;
                flag = 1;
                score++;
                for(int j=1; j<=9; j++)
                    Map[i][j] = 0;
                break;
            }
        }
        if(flag)
        {
            for(int i=hang-1; i>=1; i--)
                for(int j=1; j<=9; j++)
                    if(Map[i][j]&&Map[i+1][j]==0)
                        swap(Map[i][j],Map[i+1][j]);
        }
        else
            break;
    }
    return 1;
}

int main()
{
    // freopen( "3.out","w",stdout );
    cin>>t;
    int cs =  1;
    while(t--)
    {
        score = 0;
        scanf("%d%s",&n,ch);
        for(int i=0; i<n; i++)
            scanf("%d",&a[i]);
        memset(Map,0,sizeof(Map));
        memset(updata,0,sizeof(updata));
        jj  = 0;
        len=strlen(ch);
        for(int i=0; i<n; i++)    //下落的方块
        {
            tmp = a[i];
            memset(updata,0,sizeof(updata));
            if(a[i]==0)
            {
                updata[4][4] = 1;
                updata[3][4] = 1;
                updata[4][5] = 1;
                updata[3][5] = 1;
            }
            else if(a[i]==1)
            {
                updata[4][4] = 1;
                updata[3][4] = 1;
                updata[2][4] = 1;
                updata[1][4] = 1;
            }
            else if(a[i]==2)
            {
                updata[4][4] = 1;
                updata[3][4] = 1;
                updata[4][5] = 1;
                updata[4][6]  = 1;
            }
            for( ; jj<len; jj++)    //操作编号
            {
                if(ch[jj]!='p')
                    ctrl(ch[jj],tmp);
                 if(di())        //判断是否进行合并,消除
                {
                    jj++;
                    break;
                }
               ctrl('s',tmp);  //每次自然下落
            }
        }
        printf("Case %d: %d\n",cs++,score);
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-24 12:25:11

HDU5374 Tetris (2015年多校比赛第7场)大模拟的相关文章

HDU5374 Tetris (2015年多校比赛第7场)

1.题目描述:点击打开链接 2.解题思路:本题要求模拟俄罗斯方块游戏,然而比赛时候写了好久还是没过.后来补题发现原来是第四步的逻辑实现写错了...题目中要求如果一整行可以消除,那么仍然执行该步,否则才回到第一步.但是我的代码却是不论是否可以消除,都回到第一步...补题时候还发现一个地方我的理解出错了..(可能是我脑洞真的有点大),题目中说如果一整行可以消除,那么它上面的方格要下落.我的理解是下落的方格要一直降落到第一行或者某个支撑物上,最后发现按照这样写,样例都算不对==.调试了一下别人的代码才

HDU 5374 Tetris (2015年多校比赛第7场)

1.题目描写叙述:点击打开链接 2.解题思路:本题要求模拟俄罗斯方块游戏.然而比赛时候写了好久还是没过. 后来补题发现原来是第四步的逻辑实现写错了... 题目中要求假设一整行能够消除,那么仍然运行该步.否则才回到第一步.可是我的代码却是不论能否够消除,都回到第一步.. .补题时候还发现一个地方我的理解出错了.. (可能是我脑洞真的有点大).题目中说假设一整行能够消除,那么它上面的方格要下落.我的理解是下落的方格要一直降落到第一行或者某个支撑物上,最后发现依照这样写,例子都算不正确==.调试了一下

HDU 5399 Too Simple (2015年多校比赛第9场)

1.题目描述:点击打开链接 2.解题思路:本题分情况讨论.比赛时候真是想的太简单了,以为就是(n!)^(cnt-1).最终无限WA.本题有几个特殊情况需要额外判断.首先,如果输入的时候,有某一行不是-1且有两个数映射到同一个数,那么必然无解,ans=0.其次,如果不存在-1,需要从第m个函数一步步映射到第1个函数,检查一下最后是否真的变成了自身映射.最容易想到的情况就是有至少一个-1,那么最后答案就是(n!)^(cnt-1). 3.代码: //#pragma comment(linker, "/

HDU 5411 CRB and Puzzle (2015年多校比赛第10场)

1.题目描写叙述:pid=5411">点击打开链接 2.解题思路:本题实际是是已知一张无向图.问长度小于等于m的路径一共同拥有多少条. 能够通过建立转移矩阵利用矩阵高速幂解决.当中,转移矩阵就是输入时候的邻接矩阵,同一时候多添加最后一列,都置为1.表示从i開始的,长度不超过M的路径的答案总数(最后一行的1~n列为全0行,能够理解为空集),那么把转移矩阵自乘M-1次后就是路径长度为M的转移矩阵(这里的路径长度指的是顶点的个数.顶点=边数+1,因此仅仅须要乘M-1次). 为何便于求和.能够设置

HDU5384 Danganronpa (2015年多校比赛第8场)

1.题目描述:点击打开链接 2.解题思路:本题利用字典树解决.本题要求查找所有的B[j]在A[i]中出现的总次数.那么我们可以建立一颗字典树,将所有的B[j]插入字典树,由于一个串的所有字串相当于它所有后缀的前缀.因此在查找时候,只需要查找A[i]的每一个后缀即可,然后累加这个后缀的前缀个数,即可得到该后缀中子串的个数,所有后缀的值相加,就是最终的答案. 3.代码: #pragma comment(linker, "/STACK:1024000000,1024000000") #inc

HDU 5400 Arithmetic Sequence (2015年多校比赛第9场)

1.题目描述:点击打开链接 2.解题思路:本题利用扫描法解决.根据题意描述,[L,i)和[i,R)区间都构成了等差数列,因此可以实现用L[i],R[i]来维护从i开始向左向右可以延伸的最远长度,如果d1和d2不等,那么答案就是L[i]*R[i]求和,否则就是R[i]求和. 3.代码: //#pragma comment(linker, "/STACK:1024000000,1024000000") #include<iostream> #include<algorit

HDU 5386 Cover (2015年多校比赛第8场)

1.题目描述:点击打开链接 2.解题思路:本题利用逆向思维+贪心法解决.因为题目中已经告诉我们一定存在解,因此可以考虑贪心法的使用.这道题的妙处在于答案和初始矩阵是无关的,只和目标矩阵有关.因为不管初始矩阵长什么样,只要操作一样,加上解的存在性,得到的目标矩阵一定是相同的.接下来就是如何寻找操作序列. 假设最后一步操作执行后,我们得到了目标矩阵,由于所有操作都是对一整行或者一整列进行的,因此肯定有一行或者一列全部相同.这样,我们就可以从目标矩阵出发,逆着这个过程寻找,如果发现某一行或者一列全部相

HDU 5414 CRB and String (2015年多校比赛第10场)

1.题目描写叙述:点击打开链接 2.解题思路:本题要求推断字符串s是否能通过加入若干个字符得到字符串t. 首先,能够知道,s必须是t的一个子串(注意:不是连续子串). 第二.因为插入的新字符和它前面的字符c不同.因此假设t中有cnt个连续的c.那么在s中也必须有cnt个连续的c.因此.仅仅要能够满足这2个条件,就一定能够成功实现转化. 那么该怎样做呢?两者能够结合起来推断,用i,j分别表示s,t串中当前扫描的字符的下标.首先从字符串t開始扫描,看第一个字符c是否连续,一直到不连续为止,那么依据上

HDU 5381 The sum of gcd (2015年多校比赛第8场)

1.题目描述:点击打开链接 2.解题思路:本题利用莫队算法解决.由于是第一次学习这个算法,因此研究了比较长的一段时间才弄懂.首先,莫队算法解决的问题是无修改的离线区间查询问题.该算法实际上是由曼哈顿距离最小生成树演变来的,由于要处理m个区间,可以将这m个区间看做二维平面上的点,那么处理这m个区间就等价于让这m点连通,且总的转移代价最小.这其实就是一个曼哈顿距离最小生成树问题. 经典的曼哈顿距离最小生成树的时间复杂度是O(NlogN),莫队算法的时间复杂度是O(N^1.5).不过本题还有一个地方,