竹園論壇

標題: npsc 2013試題 A. 挑食的大胃王 [打印本頁]

作者: 林宇翔    時間: 2014-8-25 14:05
標題: npsc 2013試題 A. 挑食的大胃王
有誰會解這題




執行時間1秒
為了方便起見,老師的計算方法是先將便當切成以1 cm × 1 cm 為單位的小格子,每個格子不
是阿力會吃就是阿力不會吃。對於阿力不吃的菜,老師假設阿力會挖掉的區域為不吃的食物所存
在的格子與其上下左右相連的格子,對於所有會被挖掉的區域,阿力會挖掉3 cm 厚的白飯。示意
圖如下,下圖是一個便當的表面,0 代表是阿力會吃的食物,1 代表是阿力不吃會挖掉的食物,灰
色區域就是阿力所有會挖掉的區域,總共是18 cm2 ,因此阿力總共會挖掉18 × 3 = 54 cm3 的白
飯。
阿力可以食用的白飯量即為白飯原本的體積減掉被挖掉的白飯體積。
因為市面上的便當琳瑯滿目,因此松板老師想請你幫忙寫個程式,協助計算各種便當小朋友可
食用的白飯量是多少。

 輸入說明
輸入的第一行有一個正整數T(T  100),代表測試資料的組數。
每一組測試資料的第一行有三個正整數M,N,K (3  M,N,K  50) 分別以空白隔開。M 代
表便當的長度,N 代表便當的寬度,K 代表便當的高度。
接下來會有M 行,每行有N 個數字,分別以一個空白隔開,表示便當表面每一格是否是阿力
會吃的食物。數字由0 與1 組成,0 代表是阿力會吃的食物,1 代表是阿力不吃會挖掉的食物。
 輸出說明
對於每一筆測試資料請輸出一列,表示阿力可以食用的白飯量。

 範例輸入
2
9 10 5
0 0 0 0 0 0 0 0 0 0
0 1 1 1 0 0 0 0 0 0
0 1 1 1 0 0 0 0 0 0
0 1 1 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 1
0 0 0 0 0 0 0 0 1 1
0 0 0 0 0 0 0 0 1 1
0 0 0 0 0 0 0 0 1 1
0 0 0 0 0 0 0 0 1 1
5 5 3
0 0 0 0 0
0 1 1 0 0
0 0 0 1 1
0 0 0 0 1
0 0 1 0 0
 範例輸出
336
21






我的程式碼
不知哪裡有錯
時間又超出限制
[C++] 純文本查看 復制代碼
#include<iostream>
using namespace std;
int main()
{
        int t=0,m=0,n=0,k=0;
        cin>>t;
        int ans[t-1];
        bool yes=true;
        bool no=false;
        for(int times=0,ans_e=0;times<t;times++,ans_e++)
        {
                cin>>m>>n>>k;
                int rice[m][n],g=0,h=0,i=0;
                for(int e=0;e<m;e++)
                {
                        for(int f=0;f<n;f++)
                        {
                                cin>>rice[e][f];
                        }
                }
                for(int e=0;e<m;e++)
                {
                        for(int f=0;f<n;f++)
                        {
                                if(rice[e][f] == 1)
                                {
                                        rice[e][f]=2;
                                        //cout<<"rice["<<e<<"]["<<f<<"]"<<endl;
                                        rice[e-1][f]=2;
                                        //cout<<"rice["<<e-1<<"]["<<f<<"]"<<endl;
                                        rice[e][f-1]=2;
                                        //cout<<"rice["<<e<<"]["<<f-1<<"]"<<endl;
                                        if(rice[e+1][f] != 1)
                                        {
                                                rice[e+1][f]=2;
                                                //cout<<"rice["<<e+1<<"]["<<f<<"]"<<endl;
                                        }
                                        if(rice[e][f+1] != 1)
                                        {
                                                //cout<<"rice["<<e<<"]["<<f+1<<"]"<<endl;
                                                rice[e][f+1]=2;
                                        }
                                       
                                        i=k-3;
                                       
                                }
                                else //if(rice[e][f] == 0 && rice[e][f] != no)
                                {
                                        rice[e][f]=0;
                                }
                        }
                }
               
                for(int e=0;e<m;e++)
                {
                        for(int f=0;f<n;f++)
                        {
                                if(rice[e][f]==2)
                                {
                                        h++;
                                }
                                else
                                {
                                        g=(m*n)-h;
                                }
                                //cout<<"rice["<<e<<"]["<<f<<"]"<<endl;
                                //cout<<"g="<<g<<endl;
                                //cout<<"h="<<h<<endl;
                        }
                        //cout<<endl;
                }
                //cout<<i<<endl;
                cout<<(g*k)<<endl;
                cout<<(i*h)<<endl;
                ans[ans_e]=(g*k)+(i*h);
               
        }
        
        for(int e=0;e<t;e++)
        {
                cout<<ans[e]<<endl;
        }
        
        return 0;
}

另外
"cin 輸入經測試發現速度遠慢於scanf 輸入"
這甚麼意思



By Sylveon
請取一個適當標題



作者: Sylveon    時間: 2014-8-25 14:25
cin為了與C語言的IO相容,所以預設上,cin會多做很多動作。假若你不用scanf的話,可以加上這兩行來關閉此功能達到提升速度的效果。
什麼都不做的狀況下,cinscanf慢上2倍以上,尤其IO量很大的狀況下特別明顯。

[C++] 純文本查看 復制代碼
#include<iostream>
using namespace std;
int main()
{
        ios::sync_with_stdio(false);
        //下面三選一
        cin.tie( NULL );
        //cin.tie( 0 );
        //cin.tie( nullptr ); //C++11 support
        int a;
        cin>>a;
        cout<<"in:"<<a<<endl;
}



參考資料:http://www.hankcs.com/program/cp ... put-and-output.html

作者: Sylveon    時間: 2014-8-25 14:29
陣列請用常數宣告,這些都不是標準的C++語法

#
  • cin>>t;
  • int ans[t-1];

  • cin>>m>>n>>k;
  • int rice[m][n];


  • 作者: 林宇翔    時間: 2014-8-25 14:31
    Sylveon 發表於 2014-8-25 14:25
    cin為了與C語言的IO相容,所以預設上,cin會多做很多動作。假若你不用scanf的話,可以加上這兩行來關閉此功 ...

    我不知道我的程式哪裡寫錯
    輸出的答案都是錯的

    作者: Sylveon    時間: 2014-8-25 14:33
    林宇翔 發表於 2014-8-25 14:31
    我不知道我的程式哪裡寫錯
    輸出的答案都是錯的

    那你能分析你的程式碼如何運作嗎?  因為如果連自己的程式都不知造怎麼運行,寫出來的這個程式沒有意義
    作者: allenwhale    時間: 2014-8-25 14:54
    你的debug code有沒有拿乾淨?
    用常數宣告的意思就是用數字或是有const的變數當作長度
    [C++] 純文本查看 復制代碼
    int s1[100];
    const int N=100;
    int s2[N];
    #define MAXN 100
    int s3[MAXN];

    作者: 林宇翔    時間: 2014-8-25 15:01
    本帖最後由 林宇翔 於 2014-8-25 15:07 編輯
    Sylveon 發表於 2014-8-25 14:33
    那你能分析你的程式碼如何運作嗎?  因為如果連自己的程式都不知造怎麼運行,寫出來的這個程式沒有意義 ...

    我有加上註解
    麻煩幫我看一下

    [C++] 純文本查看 復制代碼
    #include<iostream>
    using namespace std;
    int main()
    {
            int t=0,m=0,n=0,k=0;//宣告變數
            cin>>t;//讀入測資數量
            int ans[t-1];
            for(int times=0,ans_e=0;times<t;times++,ans_e++)//多測資輸入
            {
                    cin>>m>>n>>k;//m代表y軸,n代表x軸,k代表z軸
                    int rice[m][n],g=0,h=0,i=0;
                    for(int e=0;e<m;e++)//讀入測資
                    {
                            for(int f=0;f<n;f++)
                            {
                                    cin>>rice[e][f];
                            }
                    }
                    for(int e=0;e<m;e++)//判斷是否為1,如果是1,將上下左右都編為2
                    {
                            for(int f=0;f<n;f++)
                            {
                                    if(rice[e][f] == 1)
                                    {
                                            rice[e][f]=2;
                                            //cout<<"rice["<<e<<"]["<<f<<"]"<<endl;
                                            rice[e-1][f]=2;
                                            //cout<<"rice["<<e-1<<"]["<<f<<"]"<<endl;
                                            rice[e][f-1]=2;
                                            //cout<<"rice["<<e<<"]["<<f-1<<"]"<<endl;
                                            if(rice[e+1][f] != 1)
                                            {
                                                    rice[e+1][f]=2;
                                                    //cout<<"rice["<<e+1<<"]["<<f<<"]"<<endl;
                                            }
                                            if(rice[e][f+1] != 1)
                                            {
                                                    //cout<<"rice["<<e<<"]["<<f+1<<"]"<<endl;
                                                    rice[e][f+1]=2;
                                            }
                                           
                                            i=k-3;
                                           
                                    }
                                    else //if(rice[e][f] == 0 && rice[e][f] != no)
                                    {
                                            rice[e][f]=0;
                                    }
                            }
                    }
                   
                    for(int e=0;e<m;e++)//判斷有哪些是2
                    {
                            for(int f=0;f<n;f++)
                            {
                                    if(rice[e][f]==2)
                                    {
                                            h++;
                                    }
                                    else
                                    {
                                            g=(m*n)-h;
                                    }
                                    //cout<<"rice["<<e<<"]["<<f<<"]"<<endl;
                                    //cout<<"g="<<g<<endl;
                                    //cout<<"h="<<h<<endl;
                            }
                            //cout<<endl;
                    }
                    //cout<<i<<endl;
                    //cout<<(g*k)<<endl;
                    //cout<<(i*h)<<endl;
                    ans[ans_e]=(g*k)+(i*h);//將最後答案計算出來,儲存於陣列中
                   
            }
            
            for(int e=0;e<t;e++)//顯示答案
            {
                    cout<<ans[e]<<endl;
            }
            
            return 0;
    }
    如何看程式執行時間

    作者: 林宇翔    時間: 2014-8-25 15:20
    allenwhale 發表於 2014-8-25 14:54
    你的debug code有沒有拿乾淨?
    用常數宣告的意思就是用數字或是有const的變數當作長度[mw_shl_code=cpp,true ...

    一定要這樣做嗎?
    作者: 林宇翔    時間: 2014-8-25 15:43
    你的code充斥著超出陣列的問題

    what?
    甚麼意思
    作者: allenwhale    時間: 2014-8-25 16:21
    林宇翔 發表於 2014-8-25 15:43
    what?
    甚麼意思

    以你的code為例
    當e=0,f=0時
    不會存在rice[e-1][f] and rice[e][f-1] //rice[-1][0] and rice[0][-1]
    作者: 林宇翔    時間: 2014-8-25 17:10
    allenwhale 發表於 2014-8-25 16:21
    以你的code為例
    當e=0,f=0時
    不會存在rice[e-1][f] and rice[e][f-1] //rice[-1][0] and rice[0][-1] ...

    為甚麼執行的結果答案都錯
    [C++] 純文本查看 復制代碼
    #include<iostream>
    #include<time.h>
    using namespace std;
    int main()
    {
            ios::sync_with_stdio(false);
        cin.tie( NULL );
            int t=0;//宣告變數
            int m=0,n=0,k=0;
            cin>>t;//讀入測資數量
            int ans[t-1];
            for(int times=0,ans_e=0;times<t;times++,ans_e++)//多測資輸入
            {
                    cin>>m>>n>>k;//m代表y軸,n代表x軸,k代表z軸
                    int rice[m][n],g=0,h=0,i=0;
                    for(int e=0;e<m;e++)//讀入測資
                    {
                            for(int f=0;f<n;f++)
                            {
                                    cin>>rice[e][f];
                            }
                    }
                    for(int e=0;e<m;e++)//判斷是否為1,如果是1,將上下左右都編為2
                    {
                            for(int f=0;f<n;f++)
                            {
                                    if(rice[e][f] == 1)
                                    {
                                            rice[e][f]=2;
                                            //cout<<"rice["<<e<<"]["<<f<<"]"<<endl;
                                            rice[e-1][f]=2;
                                            //cout<<"rice["<<e-1<<"]["<<f<<"]"<<endl;
                                            rice[e][f-1]=2;
                                            //cout<<"rice["<<e<<"]["<<f-1<<"]"<<endl;
                                            if(rice[e+1][f] != 1)
                                            {
                                                    rice[e+1][f]=2;
                                                    //cout<<"rice["<<e+1<<"]["<<f<<"]"<<endl;
                                            }
                                            if(rice[e][f+1] != 1)
                                            {
                                                    //cout<<"rice["<<e<<"]["<<f+1<<"]"<<endl;
                                                    rice[e][f+1]=2;
                                            }
                                           
                                            i=k-3;
                                           
                                    }
                                    else //if(rice[e][f] == 0 && rice[e][f] != no)
                                    {
                                            rice[e][f]=0;
                                    }
                            }
                    }
                   
                    for(int e=0;e<m;e++)//判斷有哪些是2
                    {
                            for(int f=0;f<n;f++)
                            {
                                    if(rice[e][f]==2)
                                    {
                                            h++;
                                    }
                                    else
                                    {
                                            g=(m*n)-h;
                                    }
                                    //cout<<"rice["<<e<<"]["<<f<<"]"<<endl;
                                    //cout<<"g="<<g<<endl;
                                    //cout<<"h="<<h<<endl;
                            }
                            //cout<<endl;
                    }
                    //cout<<i<<endl;
                    //cout<<(g*k)<<endl;
                    //cout<<(i*h)<<endl;
                    ans[ans_e]=(g*k)+(i*h);//將最後答案計算出來,儲存於陣列中
                   
            }
           
            for(int e=0;e<t;e++)//顯示答案
            {
                    cout<<ans[e]<<endl;
            }
            cout<<clock();
            return 0;
    }

    作者: Sylveon    時間: 2014-8-25 17:29
    你這code連最基本的讀取都有問題,先看看這篇文章吧
    http://forum.tfcis.org/forum.php ... typeid%26typeid%3D8
    你的答案可以算完後就直接輸出,不用存起來在一起輸出。事實上你連這裡都是錯的。
    你先寫這一題試試http://zerojudge.tw/ShowProblem?problemid=a002
    看不到哈哈哈


    作者: 林宇翔    時間: 2014-8-25 17:41
    你的答案可以算完後就直接輸出,不用存起來在一起輸出。事實上你連這裡都是錯的。

    他是所有測資都輸入完後才憶起輸出的
    如果直接輸出
    就會
    打入一次
    輸出一次
    作者: allenwhale    時間: 2014-8-25 17:46
    林宇翔 發表於 2014-8-25 17:41
    他是所有測資都輸入完後才憶起輸出的
    如果直接輸出
    就會

    題目應該沒說要一次輸出吧
    再說你思考一下,如果"輸入一次輸出一次"跟"一次輸出",對輸出檔會有甚麼不同嗎?
    理論上會是一樣的東西吧,而且當輸入很多筆的時候,你不可能會有那麼多空間可以先存起來再輸出

    至於這題,你可以參考 http://forum.tfcis.org/forum.php ... ;tid=105&extra=
    作者: 林宇翔    時間: 2014-8-25 17:51
    Sylveon 發表於 2014-8-25 17:29
    你這code連最基本的讀取都有問題,先看看這篇文章吧
    http://forum.tfcis.org/forum.php ... typeid%26typei ...
    你先寫這一題試試http://zerojudge.tw/ShowProblem?problemid=a002

    這題我對
    作者: 林宇翔    時間: 2014-8-25 17:58
    Sylveon
    那份隱藏的東西到底是啥
    作者: Sylveon    時間: 2014-8-25 17:58
    不跟你喇了

    看最簡單的一點
    #code
  • cin>>t;//讀入測資數量
  • int ans[t-1];
  • 你自己想想,給你C99標準好了,你今天有t個答案,但是你只有t-1個格子放答案,你覺得這合理嗎? 更不用說陣列大小要是常數這件事了。
    作者: 林宇翔    時間: 2014-8-25 18:09
    memset
    是啥
    作者: 林宇翔    時間: 2014-8-25 18:21
    人都不見了
    作者: Sylveon    時間: 2014-8-25 18:40
    林宇翔 發表於 2014-8-25 18:09
    memset
    是啥

    真糟糕,這東西可以解釋的很隨便,但是你有可能誤用,但是解釋得太詳細又要花時間。
    參考資料:
    http://www.cplusplus.com/reference/cstring/memset/
    http://jax-work-archive.blogspot.tw/2011/07/c-memset.html


    標頭 memory.h 不過通常用的是cstring
    函數原型: void * memset ( void * ptr, int value, size_t num );

    功能:可以快速設定一個連續的記憶體區塊(ex.陣列)的數值

    參數說明:
    ptr:作用對象的指標
    value:欲初始化的值
    num : 填充數量


    回傳值:
    ptr本身

    常見用法:
    1.把陣列所有元素都設定為0。
    在這範例裡,我們使用sizeof()運算子直接取得陣列所佔的記憶體大小。
    [C++] 純文本查看 復制代碼
    #include<iostream>
    #include<memory.h>
    using namespace std;

    int main()
    {
            int arr[5]= { 1,2,3,4,5 };
            
            memset( arr , 0 , sizeof(arr) );
            //sizeof(arr) = sizeof(int)*5
            for(int i=0;i<5;++i)
            {
                    cout<<arr<<' ';
            }
    }


    要注意,填充的單位為「位元組」,所以在這裡的sizeof(arr)不等於5,而是等於5乘以每一個int所佔的位元組
    再這種用法中除了0之外,常用的還有-1,0x3F,0x7F,後兩個通常用來代表初始化為無限大


    作者: 林宇翔    時間: 2014-8-26 10:28
    printf
    是c的輸出
    但是它可以跟c++混在一起
    是這樣嗎?
    作者: Sylveon    時間: 2014-8-26 10:50
    是的,在你不用sync with stdio時可以
    作者: 林宇翔    時間: 2014-8-26 10:58
    為什麼我重新整理跑麵包-3條
    作者: 林宇翔    時間: 2014-11-9 18:42
    這題如果這樣寫可以嗎?
    [C++] 純文本查看 復制代碼
    #include<iostream>
    #include<time.h>
    using namespace std;
    int main()
    {
        cin.tie( NULL );
            int t=0;//宣告變數
            cin>>t;//讀入測資數量  
            for(int times=0;times<t;times++)
            {
                    int m=0,n=0,k=0;
                    int ans=0;
                    cin>>m>>n>>k;//m代表y軸,n代表x軸,k代表z軸
                    int rice[m][n];
                    for(int e=0;e<m;e++)//讀入測資
                    {
                            for(int f=0;f<n;f++)
                            {
                                cin>>rice[e][f];
                            }
                    }
                    for(int e=0;e<m;e++)//判斷上下左右或自己是1,計數器加一
                    {
                            for(int f=0;f<n;f++)
                            {
                                    if(rice[e][f]==1 || rice[e-1][f]==1 || rice[e+1][f]==1 || rice[e][f+1]==1)
                                    {
                                            ans++;
                                            //cout<<ans<<'\n';
                                    }
                                    else if(f != 0 && rice[e][f]==0)
                                    {
                                            if(rice[e][f-1]==1)
                                            {
                                                    ans++;
                                                    //cout<<ans<<'\n';
                                            }
                                    }
                                    //cout<<"rice["<<e<<"]["<<f<<"]"<<'\n';
                            }
                    }
                    cout<<(m*n*k)-(ans*3)<<'\n';
                   
            }
            //cout<<clock();
            return 0;
    }

    作者: visitorIKC    時間: 2014-11-9 19:51
    本帖最後由 visitorIKC 於 2014-11-9 19:52 編輯
    林宇翔 發表於 2014-11-9 18:42
    這題如果這樣寫可以嗎?
    [mw_shl_code=cpp,true]#include
    #include

    根據我的不負責任評測機所輸出之結果,
    Wrong Answer on test 1.(line:5)
    Standard Answer: 56069
    Your Answer: 56054
    --------------------------------
    Process exited with return value 0
    Press any key to continue . . .

    UPD. Zerojudge 跑出
    (#2071516)
    第 1 測資點(0%): WA (line:3)
    答案不正确
    您的答案為: 377
    正確答案為: 380

    不知道我的評測機哪裡寫錯了
    不過你的code肯定有錯.




    歡迎光臨 竹園論壇 (http://forum.tfcis.org/) Powered by Discuz! X3.2