ccf題庫中2016年4月2日俄羅斯方塊問題

来源:http://www.cnblogs.com/JsonZhangAA/archive/2017/11/20/7868323.html
-Advertisement-
Play Games

題目如下: 網上一般是模擬方塊下落的過程,這種方法簡潔,易於理解,代碼如下: 我剛開始的想法是,為什麼不從最後一行開始,那樣不是更快嗎?後來我發現這個想法不對,從下往上找,要一直遍歷到第0行,這樣的計算量特別大。 下麵,我說說自己的想法:先通過遍歷找到對應方塊在大矩陣中的最下麵一行,然後以這個行數為 ...


題目如下:

問題描述
  俄羅斯方塊是俄羅斯人阿列克謝·帕基特諾夫發明的一款休閑游戲。
  游戲在一個15行10列的方格圖上進行,方格圖上的每一個格子可能已經放置了方塊,或者沒有放置方塊。每一輪,都會有一個新的由4個小方塊組成的板塊從方格圖的上方落下,玩家可以操作板塊左右移動放到合適的位置,當板塊中某一個方塊的下邊緣與方格圖上的方塊上邊緣重合或者達到下邊界時,板塊不再移動,如果此時方格圖的某一行全放滿了方塊,則該行被消除並得分。
  在這個問題中,你需要寫一個程式來模擬板塊下落,你不需要處理玩家的操作,也不需要處理消行和得分。
  具體的,給定一個初始的方格圖,以及一個板塊的形狀和它下落的初始位置,你要給出最終的方格圖。
輸入格式
  輸入的前15行包含初始的方格圖,每行包含10個數字,相鄰的數字用空格分隔。如果一個數字是0,表示對應的方格中沒有方塊,如果數字是1,則表示初始的時候有方塊。輸入保證前4行中的數字都是0。
  輸入的第16至第19行包含新加入的板塊的形狀,每行包含4個數字,組成了板塊圖案,同樣0表示沒方塊,1表示有方塊。輸入保證板塊的圖案中正好包含4個方塊,且4個方塊是連在一起的(準確的說,4個方塊是四連通的,即給定的板塊是俄羅斯方塊的標準板塊)。
  第20行包含一個1到7之間的整數,表示板塊圖案最左邊開始的時候是在方格圖的哪一列中。註意,這裡的板塊圖案指的是16至19行所輸入的板塊圖案,如果板塊圖案的最左邊一列全是0,則它的左邊和實際所表示的板塊的左邊是不一致的(見樣例)
輸出格式
  輸出15行,每行10個數字,相鄰的數字之間用一個空格分隔,表示板塊下落後的方格圖。註意,你不需要處理最終的消行。
樣例輸入
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 1 0 0 0
1 1 1 0 0 0 1 1 1 1
0 0 0 0 1 0 0 0 0 0
0 0 0 0
0 1 1 1
0 0 0 1
0 0 0 0
3
樣例輸出
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 1 0 0 0
1 1 1 1 1 1 1 1 1 1
0 0 0 0 1 1 0 0 0 0

網上一般是模擬方塊下落的過程,這種方法簡潔,易於理解,代碼如下:

#include<stdio.h>
#include<stdlib.h>
#include<iostream>
using namespace std;
struct Node{
    int x;
    int y;
};
int main()
{
    int s[15][10];
    Node t[4];
    for(int i=0;i<15;i++)
    {
        for(int j=0;j<10;j++)
        {
            cin>>s[i][j];
        }
    }
    int count=0;
    for(int i=0;i<4;i++)
    {
        for(int j=0;j<4;j++)
        {
            int temp;
            cin>>temp;
            if(temp==1)
            {
                t[count].x=i;
                t[count].y=j;
                count++;
            }
        }
    }
    int col;
    cin>>col;
    if(col+4>=15)
    {
        return 0;
    }else{
        for(int i=0;i<4;i++)
        {
            t[i].y+=col-1;
        }
    }
    int flag=0;
    while(1)
    {
        for(int i=0;i<4;i++)
        {
            if(s[t[i].x][t[i].y])
            {
                flag=1;
                break;    
            }
        }
        if(flag)
        {
            break;
        }else{
            for(int i=0;i<4;i++)
            {
                t[i].x++;
            }
        }
    }
    if(flag==1)
    {
        for(int i=0;i<4;i++)
        {
            s[t[i].x-1][t[i].y]=1;
        }
    }
    for(int i=0;i<15;i++)
    {
        for(int j=0;j<10;j++)
        {
            cout<<s[i][j]<<" ";
        }
        cout<<endl;
    }
    return 0;
}

我剛開始的想法是,為什麼不從最後一行開始,那樣不是更快嗎?後來我發現這個想法不對,從下往上找,要一直遍歷到第0行,這樣的計算量特別大。

下麵,我說說自己的想法:先通過遍歷找到對應方塊在大矩陣中的最下麵一行,然後以這個行數為標準來將圖形填充到大的矩陣中。詳細說明,在代碼中。

#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
using namespace std;
struct Node{
    int x;
    int y;
    int row;
};
int cmp(Node x,Node y)
{
    return x.x>y.x;
}
int main()
{
    int s[15][10];
    Node t[4];
    Node temp[4];//在這裡t用作遍歷時的數組,temp主要是方便賦值
    for(int i=0;i<15;i++)
    {
        for(int j=0;j<10;j++)
        {
            cin>>s[i][j];
        }
    }
    int count=0;
    for(int i=0;i<4;i++)
    {
        for(int j=0;j<4;j++)
        {
            int tem;
            cin>>tem;
            if(tem==1)
            {
                t[count].x=i;
                t[count].y=j;
                t[count].row=0;
                temp[count].x=i;
                temp[count].y=j;
                temp[count].row=0;
                count++;
            }
        }
    }
    int col;
    cin>>col;
    if(col+4>=15)
    {
        return 0;
    }else{
        for(int i=0;i<4;i++)
        {
            t[i].y+=col-1;
            temp[i].y+=col-1;
        }
    }
    sort(t,t+4,cmp);
    sort(temp,temp+4,cmp);
    //-----------------找出最下麵的一行------------------------- 
        int row,real_row;
        for(real_row=14;real_row>=0;real_row--){//一行一行的遍歷,從最底層開始。
            row=real_row;
            int flag;
            for(;row>=0;row--)//將從最低行一直遍歷到第0行
            {
                int temp_row=row;
                flag=0;
                for(int j=0;j<4;j++)
                {
                    if(j==0){
                        if(temp_row<0){
                            break;
                        }
                        if(s[temp_row][t[j].y]==1){
                            flag=1;//標記失敗 
                            break;
                        }else{
                            temp_row=temp_row-t[j].x+t[j+1].x;
                        }
                    }else{
                        if(temp_row<0){
                            break;
                        }
                        if(s[temp_row][t[j].y]==1){
                            flag=1;//標記失敗 
                            break;
                        }else{
                            if(j<=2){
                                temp_row=temp_row-t[j].x+t[j+1].x;    
                            }
                        }
                    }        
                }
                if(flag==1){//出現失敗後沒有必要在遍歷了,跳出迴圈,對下一個real_row進行從real_row到0的遍歷
                    break;
                }
            }
            if(flag==0){//說明出現了滿足情況的行數,停止執行。
                break;
            }
        }
    //--------------重新賦值--------------------
//    cout<<"最終行數為:"<<real_row<<endl;
    for(int i=0;i<4;i++)
    {
        if(i==0){
            temp[i].x=real_row;
            real_row=real_row-t[0].x+t[1].x;
        }else{
            temp[i].x=real_row;
            if(i<=2){
                real_row=real_row-t[i].x+t[i+1].x;//利用小矩陣中函數差,來確定對應的大矩陣中的行數,例如,t[0]在小矩陣中是第二行,t[1]在小矩陣中是第一行,t[0]在大矩陣中是第13行,那麼t[1]應該是13-2+1=12行
            }
        }
        s[temp[i].x][temp[i].y]=1;
    }
    //--------------輸出結果-------------------- 
    for(int i=0;i<15;i++)
    {
        for(int j=0;j<10;j++)
        {
            cout<<s[i][j]<<" ";
        }
        cout<<endl;
    }
    return 0;
}

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 通過下麵一個例子進行理解。 運行結果: 分析: p = multiprocessing.Process(……)定義了五個進程,p.start五個進程並行,造成如圖的結果是信號量限制進程對臨界資源的訪問的原因。 s = multiprocessing.Semaphore(2)定義了信號量最大為2,re ...
  • 前言 今天要總結的就是Mybatis的相關簡單入門,並且使用這個持久化框架解決一些JDBC原生代碼產生的問題。 一、Mybatis介紹 MyBatis本是apache的一個開源項目iBatis,2010年這個項目由apache software foundation 遷移到了google code, ...
  • 定義 原型(Prototype Pattern)是一個簡單的設計模式。原型模式的英文原話是:Specify the kind of objects to create using a prototypical instance,and create new objects by copying th ...
  • 測試環境 本次測試直接host指定功能變數名稱,然後在虛擬機中安裝了三台CentOS。 測試功能變數名稱 :a.com A伺服器IP :192.168.0.108(主) B伺服器IP :192.168.0.27 C伺服器IP :192.168.0.131 部署思路A伺服器做為主伺服器,功能變數名稱直接解析到A伺服器(192 ...
  • 前面的隨筆中我們經常會改setting配置也經常將一些配置混淆今天主要是將一些常見的配置做一個彙總。 ...
  • 題目如下: 這題思路比較簡單,我們可以寫一個檢測函數func來測試一位數組中重覆元素大於或等於3的情況。然後在主函數中分別對每列和每行執行func運算。 代碼如下: ...
  • 很多招聘網上找php程式員的時候都說要懂xml,這個xml+php在web網站開發方面到底有什麼應用呢,希望有知道的朋友能給我具體說說,謝謝了! 我說的是在網站中的實際應用有哪些,不是網上抄的xml的介紹,比如說是資料庫中的數據寫入到xml中,然後再顯示到前臺頁面上等等。 這個很有用,比如開發一個接 ...
  • 在使用普通的 JDBC 資料庫時,就會很麻煩的寫不必要的代碼來處理異常,打開和關閉資料庫連接等。但 Spring JDBC 框架負責所有的低層細節,從開始打開連接,準備和執行 SQL 語句,處理異常,處理事務,到最後關閉連接。所以當從資料庫中獲取數據時,你所做的是定義連接參數,指定要執行的 SQL ... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...