100北二區資訊複賽
1.圈叉連線數問題(zj:a817) ✔(上次已傳)
2.藏寶問題(zj:a824) ✔(上次已傳)
3.小四數學(zj:a825) ✔(上次已傳)
4.天氣預測問題(zj:a826) ✔(上次已傳)
5.俄羅斯方塊問題(zj:a827)
101北二區資訊複賽
1.解碼問題(zj:a818) ✔(上次已傳)
2.小三資優數學(zj:a819) ✔
3.小精靈吃數字(zj:a820) ✔(上次已傳)
4.王者之路(zj:a821) ✔(上次已傳)
5.滾球遊戲(zj:a822) ✔(上次已傳)
100年5.俄羅斯方塊問題(zj:a827) ================
// a827. 5.俄羅斯方塊問題 -- 100學年度桃竹苗區資訊學科能力競賽
#include <iostream>
#include <cstring>
#include <set>
using namespace std;
const int BitN = 8; // 牆寬 8 格
const int BoxN = 11; // 11 種 (含旋轉)的方塊
int box[BoxN][2]={{3,3}, {0,15}, {1,1}, {3,1}, {3,6}, {3,2}, {6,3}, {2,7}, {7,2}, {3,2}, {3,1} }; // 每種2列
int bw[BoxN] = { 2, 4, 1, 2, 3, 2, 3, 3, 3, 2, 2}; // 11種 方塊的 寬度
int ty[BoxN] = {1, 2,2, 3,3, 4,4, 5,5,5,5 }; //屬於哪一種類型
int w[2]; // 牆 2列
set<int> out;
set<int>::iterator it;
int chk(int bi )
{
int i,b0,b1, sco, tot=0;
for(i=BitN-bw[bi]; i>=0; --i)
{
b1 = box[bi][1]<<i ; // 小方塊的下方列 由左至右的值
if( b1&w[0] ) continue; // bit and 值非 0 即無法放入第1層
// 進入第1層,接著檢查是否可進入第2層
b0 = box[bi][0]<<i ; // 小方塊的上方列 由左至右的值
if( (b0&w[0]) == 0 && (b1&w[1]) == 0 ) // 2層皆進入 , 因運算序(bit and)需括住
{
sco = ( ((b0|w[0])==255) + ((b1|w[1])==255) ) * 8; // 因運算序(bit or)需括住
} else { // 只能進一層,算第1層的分數
sco = ( (b1|w[0]) == 255 ) * 8;
}
if( sco>tot ) tot=sco;
}
return tot;
}
int main(void)
{
int i,j;
string s;
// 讀入兩列 牆
for(i=0; i<2; ++i) // 2列
{
cin >> s;
w[i] = 0;
for(j=0; j<BitN; ++j)
w[i] = w[i]*2 + (s[j]=='*');
}
int mx=0 , sco;
for( i=0; i<BoxN; ++i) // 以 11種 方塊各求 可得的分數,最高的 放入 out
{
sco = chk(i);
if( sco==0 || sco<mx ) continue;
if( sco>mx ) out.clear();
mx=sco;
out.insert( ty[i] ); // 若分數 >= mx 加入 out , 數字同 set只有1個
}
if( mx == 0 ) cout << "0\n0\n"; // 印2列 0
else { //最少一個
it = out.begin();
cout << (*it) ;
for(++it; it!=out.end(); ++it)
cout << ' ' << (*it) ;
cout << endl << mx << endl;
}
return 0;
}
/* ----範例輸入
例一 :
000*0000
****0***
例二 :
***0****
***0****
-----------範例輸出
例一 :
2 4 5
8
例二 :
2
16
*/
1.圈叉連線數問題(zj:a817) ✔(上次已傳)
2.藏寶問題(zj:a824) ✔(上次已傳)
3.小四數學(zj:a825) ✔(上次已傳)
4.天氣預測問題(zj:a826) ✔(上次已傳)
5.俄羅斯方塊問題(zj:a827)
101北二區資訊複賽
1.解碼問題(zj:a818) ✔(上次已傳)
2.小三資優數學(zj:a819) ✔
3.小精靈吃數字(zj:a820) ✔(上次已傳)
4.王者之路(zj:a821) ✔(上次已傳)
5.滾球遊戲(zj:a822) ✔(上次已傳)
100年5.俄羅斯方塊問題(zj:a827) ================
// a827. 5.俄羅斯方塊問題 -- 100學年度桃竹苗區資訊學科能力競賽
#include <iostream>
#include <cstring>
#include <set>
using namespace std;
const int BitN = 8; // 牆寬 8 格
const int BoxN = 11; // 11 種 (含旋轉)的方塊
int box[BoxN][2]={{3,3}, {0,15}, {1,1}, {3,1}, {3,6}, {3,2}, {6,3}, {2,7}, {7,2}, {3,2}, {3,1} }; // 每種2列
int bw[BoxN] = { 2, 4, 1, 2, 3, 2, 3, 3, 3, 2, 2}; // 11種 方塊的 寬度
int ty[BoxN] = {1, 2,2, 3,3, 4,4, 5,5,5,5 }; //屬於哪一種類型
int w[2]; // 牆 2列
set<int> out;
set<int>::iterator it;
int chk(int bi )
{
int i,b0,b1, sco, tot=0;
for(i=BitN-bw[bi]; i>=0; --i)
{
b1 = box[bi][1]<<i ; // 小方塊的下方列 由左至右的值
if( b1&w[0] ) continue; // bit and 值非 0 即無法放入第1層
// 進入第1層,接著檢查是否可進入第2層
b0 = box[bi][0]<<i ; // 小方塊的上方列 由左至右的值
if( (b0&w[0]) == 0 && (b1&w[1]) == 0 ) // 2層皆進入 , 因運算序(bit and)需括住
{
sco = ( ((b0|w[0])==255) + ((b1|w[1])==255) ) * 8; // 因運算序(bit or)需括住
} else { // 只能進一層,算第1層的分數
sco = ( (b1|w[0]) == 255 ) * 8;
}
if( sco>tot ) tot=sco;
}
return tot;
}
int main(void)
{
int i,j;
string s;
// 讀入兩列 牆
for(i=0; i<2; ++i) // 2列
{
cin >> s;
w[i] = 0;
for(j=0; j<BitN; ++j)
w[i] = w[i]*2 + (s[j]=='*');
}
int mx=0 , sco;
for( i=0; i<BoxN; ++i) // 以 11種 方塊各求 可得的分數,最高的 放入 out
{
sco = chk(i);
if( sco==0 || sco<mx ) continue;
if( sco>mx ) out.clear();
mx=sco;
out.insert( ty[i] ); // 若分數 >= mx 加入 out , 數字同 set只有1個
}
if( mx == 0 ) cout << "0\n0\n"; // 印2列 0
else { //最少一個
it = out.begin();
cout << (*it) ;
for(++it; it!=out.end(); ++it)
cout << ' ' << (*it) ;
cout << endl << mx << endl;
}
return 0;
}
/* ----範例輸入
例一 :
000*0000
****0***
例二 :
***0****
***0****
-----------範例輸出
例一 :
2 4 5
8
例二 :
2
16
*/