顯示具有 P2A 標籤的文章。 顯示所有文章
顯示具有 P2A 標籤的文章。 顯示所有文章

2017年6月15日 星期四

2017年5月29日 星期一

2017年5月22日 星期一

b547 巧克力口味

/*
b547-巧克力口味
*/

#include <iostream>
#include <sstream>
#include <iomanip>
#include <cstring>
#include <cstdio>
#include <vector>
#include <map>
#include <set>
#include <algorithm>

using namespace std;
const int MaxR = 10;
set <string> rel[MaxR];  // 最多 10 種 關係
map <int , int> c2n;
string rs(8,'?');

string c6(6,' ');
int getn(int i)
{
int j=c2n[ c6[i] ];
j += c2n[ c6[i+1] ];
return j;
}
// 以遞迴 將某一關係的所有編號建立 存入 rel[si]中
string ss[]={"PBY","SCT"};
void setr(int si, int p, int q)
{
int i,j;
if(q==6) // 已 6個字元了
{
bool mk[10];
string one="";
memset(mk,0,sizeof(mk));
for(i=0; i<6; i+=2)
{
j= getn(i);
if( mk[j] ) return; // 出現過,不合
mk[j] = true;
one += char('0'+j);
}
rel[si].insert(one);  // 可以的關係編號 加入 rel[si] 中
//// cout << si <<':' << one << endl;  /////
}
else  // 完成第 q 個字元,遞迴下一字元 q+1
{
if( rs[p+q]=='?' )  // 目前這個位置為 ?  偶則以 PBY各代1次、 奇則以 SCT各代1次
  for(i=0; i<3; ++i)
  {
  c6[q] = ss[q%2][i]; setr(si, p, q+1);
  }
else
{
c6[q] = rs[p+q]; setr(si, p, q+1);
}
}
}

string x,y,z; // 將nine切成3部份
int r;  //共 r 個關係
bool ok()   // 任一個關係  最少要有 某一列 3個巧克力 符合它
{
for(int si=0; si<r; ++si)
{
if( !( rel[si].find(x)!=rel[si].end()  ||  rel[si].find(y)!=rel[si].end()  ||  rel[si].find(z)!=rel[si].end()  )  ) return false;
}
return true;
}

int main(void)
{
int i,j,k,t ,n;
char c;
c2n.clear();
c2n['P']=0; c2n['B']=3; c2n['Y']=6;
c2n['S']=1; c2n['C']=2; c2n['T']=3;

cin >> r;
for(i=0; i<r; ++i)
{
cin >> t;
for(j=0; j<t*2; ++j)
{
cin >> rs[j+2];/// >> rs[j+3];  
}
/// cout << i <<':' << rs << endl;   ////
if(t==3) setr(i,2,0);   // 第i個關係,從第2字元、已轉了0個
else // t=2 , 前?? 及後 ?? 各一次
{
setr(i,0,0);   // 第i個關係,從第0字元、已轉了0個
rs[6] = rs[7] ='?';
setr(i,2,0);   // 第i個關係,從第2字元、已轉了0個
}
}
string nine="123456789";
//   cout << nine << endl;   1~9 九位數,全排列  共 9! =  362880
   int cnt=0;
do
{
x=nine.substr(0,3); y=nine.substr(3,3); z=nine.substr(6,3);
// cout << x <<',' << y <<',' << z <<'\n';
if( ok() ) ++cnt;
   } while( next_permutation(nine.begin(),nine.end() ) );
cout << cnt << endl;

// system("pause");
return 0;
}
/*
3
3 B S Y S P C
3 P T B C Y T
3 P S B T Y C

3
3 B S Y ? ? C
2 B C Y T
3 P S ? ? Y C

==========
6
24

*/


2017年5月20日 星期六

b549 數位相片檔名

/*
b549 nr102-5 北二區102年-5 數位相片檔名 
*/
#include <iostream>
#include <iomanip>
#include <set>
#include <map>
using namespace std;

map<int,int> used;                   // 已使用的 <時間 , 檔名>
map<int,int>::iterator mit;
map<int,int>::reverse_iterator rit;

bool can(int fn)                     // 傳入的檔名是否可用(符合雙遞增)
{
    if(used.size()<2) return true;    // 只有0或1個時,一定可以 
   int cnt=1;                        // 使用的 序列數,最多2個  
   mit=used.begin();                
   int fn1=mit->second, fn2=9999 ,fn3;   //第1個使用 一個序列 
   // 若有兩個序列,維持 fn1<fn2 
   for(++mit; mit!=used.end() ; ++mit)  // 從 第2個起與前一個比 
   {
    fn3=mit->second; // 第2個起的檔案編號
    if( fn3<fn1 )
    {
    if (cnt==2 )  return false;  //已兩個再加1個 x
    ++cnt; fn2=fn1; fn1=fn3;  //保持 fn1<fn2
    }
    else // fn3>fn1 可加入 fn1或fn2
{
if(fn3>fn2) fn2=fn3; //加至較大 的序列處,保留較小的序序編號 
else fn1=fn3;   // fn3<fn2無法加至 fn2,也保證 fn1=fn3<fn2 
}
   }
   if( cnt==2 && fn<fn1 ) return false;  //已兩個再加1個 x
   else return true;
}

int main( )

{
   int n , t ;
   int fn[1000];
   char c;
   for( n=0; n<1000; ++n) fn[n] = n;
    set <int>::iterator sit;  
   bool first=true;
   while( cin >> n )
   {
      set <int> nuse(fn,fn+1000);  //待用的檔號
      used.clear();      

       while( n-- )
       {
          cin >> c >> t;
           if( c == 'A' )
          {
             for( sit = nuse.begin(); sit != nuse.end(); ++sit )
             {
                int fn = *sit;   //檢查檔名編號 fn 是否可用
                if ( !can( fn ) ) continue;   // 不能用,下一個
                used[ t ] = fn;             // t 時,加可用檔名 fn
                nuse.erase( *sit );
                break;
             }
          }
          else
          {
             nuse.insert( used[t] );   // 未用的檔名,加一個
             used.erase( t );          // 已用的 map <t,fn> 刪一個
          }
       }
// 印出,若不是第一組,則印出 --
        if(first) first=false; else cout << "--\n";  
        rit = used.rbegin();  rit++;  //先至倒數第2個 
        cout << "PIC" << setfill ('0') << setw (3) << (rit->second) << endl;
        rit--;
        cout << "PIC" << setfill ('0') << setw (3) << (rit->second) << endl;
   }
   return 0 ;
}

/* 輸入範例 
10 A 0  A 1  A 2  A 3  D 2 A 4 D 1 A 5 D 4 A 6
14 A 0  A 1  A 2  A 3  D 2 A 4 D 1 A 5 D 4 A 6 D 3 A 7 D 0 A 8
14 A 0  A 1  A 2  A 3  D 2 A 4 D 1 A 5 D 5 A 6 A 7 D 0 A 8 A 9
14 A 0  A 1  A 2  A 3  D 2 A 4 D 1 A 5 D 5 A 6 A 7 A 8 D 4 A 9
15 A 0  A 1  A 2  A 3  D 2 A 4 D 1 A 5 D 5 A 6 A 7 A 8 D 4 A 9  A 10
17 A 0  A 1  A 2  A 3  D 2 A 4 D 1 A 5 D 5 A 6 A 7 A 8 D 4 A 9  A 10 D 6 A 11
19 A 0  A 1  A 2  A 3  D 2 A 4 D 1 A 5 D 5 A 6 A 7 A 8 D 4 A 9  A 10 D 6 A 11 D 11 A 12
9 A 0 A 1 A 2 A 3 D 2 A 4 D 1 D 0 A 5
9 A 0 A 1 A 2 A 3 D 2 A 4 D 1 A 5 A 6
10 A 0 A 1 A 2 A 3 A 4 D 2 A 5 A 6 D 3 A 7
輸出範例-----------------
PIC004
PIC001
--
PIC002
PIC003
--
PIC006
PIC007
--
PIC006
PIC001
--
PIC001
PIC002
--
PIC002
PIC004
--
PIC002
PIC004
--
PIC002
PIC004
--
PIC004
PIC005
--
PIC005
PIC003
*/

2017年3月23日 星期四

Y7M3 P2A 練習-7 俄羅斯方塊

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
*/

2017年3月20日 星期一

Y7M3 P2A 練習-6 小三資優數學

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)                   ✔(上次已傳)

101年2.小三資優數學(zj:a819)  ================ 
// a819. 2.小三資優數學 -- 101學年度桃竹苗區資訊學科能力競賽
/*
a819 小三數學,三個數字三列,第1列:n{2~10}代表位數,第2列:k{n位的數字},第3列:可算出的結果 m
     n位數k的每位數之間可加運算符號使結果等於 m ,最多可加兩個符號{符號為 + , - , * , / 四種}兩個符號可相同 
     ===*** 題目中未說明,但若 先÷再*,暫時規定需能整除才加除號;例如  12/8*6不可以,不接受右列結果 {1.5*6=9、1*6=6}
*/

#include <iostream>
using namespace std;
typedef long long LL;
const LL INF = 1e18;
int n,m ; //, cnt;
string s;
LL a,b,c;

LL cal(LL x, LL y , char op)  // 算出 x (op) y : op是+-*/
{
switch(op)
{
case '+': //+
 return x+y; break;
case '-': //-
 return x-y; break;
case '*': //*
 return x*y; break;
case '/': // ÷  y<>0且x÷y需整除,否則傳回 INF(不成立)
 if(y && x%y==0) return x/y; else return INF;
 break;
}
}
char ops[]={'-','+','*','/'};
void cut2(int p) // 將讀入的 數字串 s,切成左右兩部份:加1個符號在 索引 p之前
{                // 即 s[0~p-1] 一段轉成數值 a、 s[p~n-1] 一段 轉成數值 b
int i;
for(a=0, i=0; i<p; ++i) a=a*10+s[i]-'0';
for(b=0, i=p; i<n; ++i) b=b*10+s[i]-'0';
for(int op=0; op<4; ++op)
{
LL r = cal(a,b,ops[op]);
// cout << a <<ops[op] <<b <<'=' << r << endl;  //
if(r!=m) continue;
cout << a << ops[op] <<b << endl;
// ++cnt;
}
}

void cut3(int p, int q) // 將讀入的 數字串 s,切成三部份:加2個符號 {索引 p之前,索引 q之前}
{            // 即 s[0~p-1] 一段轉成數值 a、 s[p~q-1] 一段 轉成數值 b  s[q~n-1] 一段 轉成數值 c
int i,op1,op2;
for(a=0, i=0; i<p; ++i) a=a*10+s[i]-'0';
for(b=0, i=p; i<q; ++i) b=b*10+s[i]-'0';
for(c=0, i=q; i<n; ++i) c=c*10+s[i]-'0';
// cout << a <<','<<b<<','<<c<<endl;    //
//// === *** 運算式的優先序,先乘除後加減,應可建一個表以簡化程式碼,但我懶得再改了
for( op2=0; op2<4; ++op2)  // r2 = b { + -  * / } c 先 , 再 a{+-}r2 除了  - + 或 - -
{
LL r2 = cal(b,c,ops[op2]);
// cout << a <<ops[op] <<b <<'=' << r << endl;  //
if(r2 == INF) continue;
for( op1=0;op1<2; ++op1)
{
if(op1==0 && op2<2) continue;
LL r1 = cal(a,r2,ops[op1]);
//   cout << a << ops[op1] <<b << ops[op2] <<c <<'=' << r1 << endl;  //
if(r1 !=m ) continue;
  cout << a << ops[op1] <<b << ops[op2] <<c << endl;
//   ++cnt;
}
}
LL r = cal( cal(a,b,'-') , c , '+' );  // a-b+c
// cout << a << '-' <<b << '+' <<c  <<'=' << r << endl;  //
if (r==m) {  cout << a << '-' <<b << '+' <<c << endl;  } //  ++cnt; } 
r = cal( cal(a,b,'-') , c , '-' );  // a-b-c
// cout << a << '-' <<b << '-' <<c  <<'=' << r << endl;  //
if (r==m) { cout << a << '-' <<b << '-' <<c << endl;  } //  ++cnt; } 

for( op1=2; op1<4; ++op1)  // r1 = a{ * / } b 先 , 再 r1{+-*/} c ,除了 a/b*c
{
LL r1 = cal(a,b,ops[op1]);
// cout << a <<ops[op] <<b <<'=' << r << endl;  //
if(r1 == INF) continue;
for( op2=0;op2<4; ++op2) // 除了 a/b*c 先算 a*c/b
{
if(op1==3 && op2==2) continue;
LL r2 = cal(r1,c,ops[op2]);
//   cout << a << ops[op1] <<b << ops[op2] <<c <<'=' << r2 << endl;  //
if(r2 !=m ) continue;
cout << a << ops[op1] <<b << ops[op2] <<c << endl;
// ++cnt;
}
}
r = cal( cal(a,c,'*') , b , '/' );  // a/b*c => a*c/b ,例 9/6*4 = 6
// cout << a << '/' <<b << '*' <<c <<'=' << r<< endl;     //
if (r!=m) return;
cout << a << '/' <<b << '*' <<c << endl;
// ++cnt;
}

int main(void)
{
int i,j;
cin >> n >> s >> m;
// {
LL k=0;
for(i=0; i<n; ++i) k=k*10+s[i]-'0';
if(k==m) { 
 cout << s << endl;
 return 0;
}
  // cnt =0;
for(i=1; i<n; ++i)  //切成 2 部份,切點位置 p:1~n-1
cut2(i);
for(i=1;i<n-1;++i)
 for(j=i+1; j<n; ++j)  //切成 3 部份,切點位置 p:1~n-2 , q:p+1~n-1
   cut3(i,j);
// if(cnt==0) cout << s<<','<<m<<endl;
// }

return 0;
}
/*

*/


/*  ----範例輸入
例一 : 12/3 = 4
3
123
4
例二 : 2+3*4 = 14
3
234
14
例三 : 240/15 = 16
5
24015
16
例四 : 8-6+2
3
862
4
例五 9/6*4 <<此例應不成立
3
964
6
例六  1357-924*680
10 
1357924680 
-626963
-----------範例輸出
12/3
2+3*4
240/15
8-6+2
9/6*4
1357-924*680

*/