顯示具有 C++ 標籤的文章。 顯示所有文章
顯示具有 C++ 標籤的文章。 顯示所有文章

2009年6月5日 星期五

燈泡開關 與 遇見一株樹 (C語言)

//===============================================================
// 20090605 知識 +
// http://tw.knowledge.yahoo.com/question/question?qid=1009060510662
// 附件: http://tioj.redirectme.net:8080/JudgeOnline/showproblem?problem_id=1106
// 發問者 :(ARX-7 ) http://tw.knowledge.yahoo.com/my/my?show=AC04610971
//===============================================================

這有兩個題目: (1)燈泡開關 與 (2)遇見一株樹
而這類題目都假定提供的數據都是正確的, 而求得 輸出結果.

(1) 燈泡開關 的程式碼 --


#include <stdio.h>
#include <stdlib.h>

const int Max=100000;
const unsigned int MaxNo = (unsigned int)1<<31;
// === 主程式 ===
int main()
{
int N, i, l, use; // use : 亮燈的數量
unsigned int bulbNo; // 因燈號可達 2^31, 故需用無號int (32bits)
unsigned int Light[Max]; // 燈亮紀錄; 實際只要 Max/2+1 即可
FILE *file = fopen( "bulb.txt", "r");
if (file==NULL) file=stdin; // 若無bulb.txt 則人工輸入(Ctrl+Z結束)
while(fscanf(file, "%d", &N)==1 && N>0 && N<=Max) // 取得筆數
{
for(use=0, i=0; i<N; i++) // 用迴圈來取得 N 筆資料
{
if (fscanf(file, "%u", &bulbNo)!=1 || bulbNo > MaxNo) break;
for(l=0; l<use && Light[l]!=bulbNo; l++); // 是否為燈亮?
if (l<use) Light[l]=Light[--use]; // 是!! 滅燈(挪最後燈來蓋掉紀錄)
else Light[use++]=bulbNo; // 否!! 在末端紀錄燈亮
}
if (i<N || use!=1) break; // 資料有誤--資料取得有誤 或 未剩一盞燈
printf("%u\n", Light[0]);
}
if (file!=stdin) fclose(file);
return 0;
}
//==============
bulb.txt 檔案內容範例 :
5
1 2 3 2 1
7
0 0 0 777 0 0 0


(2) 遇見一株樹 的程式碼 --


#include <stdio.h>
#include <stdlib.h>

const int Max=100001; //樹的長度不超過100,000個字元, 多保留一位讀字串補\0

int ParseTree(char *tree, int *leaf, int *depth, int *ary, int d)
{ // d: 傳入的深度
int p, a; // p:字串處理位置 a:項次數
for(p=0, a=0; tree[p]=='*' || tree[p]=='('; p++, a++)
{
if(tree[p]=='*') *leaf+=1; // 統計葉子數量
else p+= ParseTree(tree+p+1, leaf, depth, ary, d+1); // '(' 遞迴
}
if (d>*depth) *depth=d; // 傳回最深深度
if (d>1 && a>*ary) *ary=a; // 傳回子項(深度大於1)中,最大項次數
return p+1; // 回傳所處理的位置(長度)
}
// === 主程式 ===
int main()
{
char tree[Max];
int leaf, depth, ary;
FILE *file = fopen( "tree.txt", "r");
if (file==NULL) file=stdin; // 若無tree.txt 則人工輸入(Ctrl+Z結束)
while(fgets(tree, Max, file)!=NULL)
{
leaf=depth=ary=0;
ParseTree(tree, &leaf, &depth, &ary, 1); // 解析 字串樹
printf( "%d %d %d\n", leaf, depth, ary);
}
if (file!=stdin) fclose(file);
return 0;
}
//==============

tree.txt 檔案內容範例 :
*
((((((*))))))
(*******)
(*(**)(*))

2009年5月26日 星期二

循環式質數 (c/c++)

//===============================================================
// 20090521 知識 +
// http://tw.knowledge.yahoo.com/question/question?qid=1009052111388
// 發問者 :(兔〞man〃 ) http://tw.knowledge.yahoo.com/my/my?show=AB01282140
//===============================================================


#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

const int _max = 100000; // 質數表大小
int prime[_max] = { 2, 3, 5, 7, 11 };
int _lx;
// --- 建立質數表
void initPrime()
{
int p, x=4, i=5;
for(int n=13; i<_max; n+=x, x=6-x)
{
int q = (int)sqrt((double)n);
for(p=1; p<i && prime[p]<=q; p++)
if (n%prime[p]==0) p=i;
if (p<i) prime[i++] = n;
}
_lx = 6-x;
return;
}
// --- 檢查是否為質數
bool IsPrime(long long num)
{
int i = (int)(num%6);
if (num>6 && i!=1 && i!=5) return false;
long q = (long) sqrt((long double)num);
for(i=2; i<_max && prime[i]<=q; i++)
if (num%prime[i]==0) return false;
if (i<_max) return true;
long n = prime[_max-1]+_lx;
for(i=_lx ;n<=q; n+=i, i=6-i)
if (num%n==0) return false;
return true;
}
// --- 指定位數的循環式質數檢查
char d[4] = { 1, 3, 7, 9 };
char a[16];
void checkN(int n)
{
printf( "\n %d 位數:", n );
int i, m, c, l, o=1, max = 1;
for(i=0; i<n; i++) { max*=4; o*=10; }
for(l=0, o/=10; l<max; l++)
{
for(i=n-1, m=l; i>=0; i--, m/=4) a[i]=d[m%4];
for(i=0, c=0; i<n; i++) c=c*10+a[i];
for(i=0, m=c; i<n; i++, m=m/10+m%10*o)
if (!IsPrime(m)) break;
if (i==n) printf( " %d", c );
}
printf("\n");
}
// --- 檢查是否為循環式質數
bool checkNum(int c)
{
int m, n, o, i;
for(m=c, n=0; m>0; m/=10) n++; // 計算位數
// if (n<2 || n>8 ) return false;
for(i=1, o=1; i<n; i++) o*=10; // 偏移值
for(i=0, m=c; i<n; i++, m=m/10+m%10*o) //循環
if (!IsPrime(m)) return false;
return true;
}
// =========== 主程式 ============
int main()
{
clock_t start = clock();
initPrime();
clock_t begin = clock();
printf( "\n循環式質數 總覽 -- \n");
for(int nn=2; nn<9; nn++) checkN(nn);
clock_t end = clock();
printf( "\n總計時間: %.3fsec. 質數表建立時間: %.3fsec. 處理時間: %.3fsec.\n\n",
(double)(end-start)/CLOCKS_PER_SEC, (double)(end-begin)/CLOCKS_PER_SEC,
(double)(begin-start)/CLOCKS_PER_SEC );
//------------
int d;
while(1)
{
printf("\n請輸入一個2~9位數值, 將檢測其是否為循環式質數 :");
if (scanf("%d", &d)!=1 || d<10 || d>999999999) break;
if (checkNum(d)) printf("○ %d是一個循環式質數!!\n", d);
else printf("╳ %d不是一個循環式質數!!\n", d);
}
return 0;
}
//====================================================

函式指標 計算應用 (C)

//===============================================================
// 20090523/24/26 知識 +
// http://knowledge.yahoo.com.tw/question/question?qid=1609052303386
// http://knowledge.yahoo.com.tw/question/question?qid=1609052411327
// http://knowledge.yahoo.com.tw/question/question?qid=1609052606389
// 發問者 :( ) http://tw.knowledge.yahoo.com/my/my?show=AB04901004
//===============================================================


#include <stdio.h>
#include <stdlib.h>
#include <math.h>

typedef double T (double *Op1, double *Op2);
T add, sub, mul, div, fac, por;
T *pM[] = { add, sub, mul, div, fac, por };
char* msg[] = { "相加", "相減", "相乘", "相除", "階乘", "次方" };

//=========== 主程式 ...
int main(void)
{
double ans, Op1, Op2;
int i, num, opN = sizeof(pM)/sizeof(*pM);
while(1)
{
printf("\n要做哪種運算? ");
for(i=0; i<opN; i++) printf("%d)%s ", i, msg[i]);
printf(",其它)離開 \n");
if (scanf("%d",&num)!=1 || num<0 || num >= opN) break;
ans = pM[num](&Op1, &Op2);
printf("%s的結果 = %.2lf \n", msg[num], ans);
}
system("pause");
return 0;
}

//---------
double Input(int no, int mode=-1)
{
double d;
while(!fflush(stdin)) //淨空輸入
{
printf("請輸入第%d個數值 : ", no );
if (scanf("%lf", &d)!=1) printf("輸入錯誤!! 重新");
else if (mode==0 && d==0) printf("數值不得為0!! 重新");
else break;
}
return d;
}

int InputInt()
{
int n;
while (!fflush(stdin)) //淨空輸入
{
printf( "請輸入一個整數 : " );
if (scanf("%d", &n)==1) break;
printf("輸入錯誤!! 重新");
}
return n;
}
//---------
double add(double *Op1, double *Op2)
{
*Op1 = Input(1); *Op2 = Input(2);
return (*Op1) + (*Op2);
}

double sub(double *Op1, double *Op2)
{
*Op1 = Input(1); *Op2 = Input(2);
return (*Op1) - (*Op2);
}

double mul(double *Op1, double *Op2)
{
*Op1 = Input(1); *Op2 = Input(2);
return (*Op1) * (*Op2);
}

double div( double *Op1, double *Op2)
{
*Op1 = Input(1); *Op2 = Input(2, 0);
return (*Op1) / (*Op2);
}

double fac(double *Op1, double *Op2)
{
double ans = 1; *Op2 = 0;
int num = InputInt();
for( *Op1 = num; num>=2; num--) ans *= num;
return ans;
}

double por(double *Op1, double *Op2)
{
*Op1 = Input(1); *Op2 = Input(2);
return pow(*Op1, *Op2);
}
//---------------------------------

2009年5月3日 星期日

C語言 數獨解題程式

//=================================================================
// 20090501 知識 +
// http://tw.knowledge.yahoo.com/question/question?qid=1009050109126
// 發問者 : (小小) http://tw.knowledge.yahoo.com/my/my?show=AE03326172
//=================================================================


#include <stdio.h>
#include <stdlib.h>

void Show(int b[][9]);
int Promising(int b[][9], int n);
int Tracking(int b[][9], int n);

int Sol[9*9];
int Cnt=0;
int Ans=0;

int main()
{
int board[9][9] = {
{ 0, 0, 0, 0, 5, 0, 0, 0, 0 },
{ 0, 7, 0, 0, 0, 3, 0, 2, 0 },
{ 4, 5, 0, 0, 0, 1, 0, 0, 8 },
{ 0, 0, 2, 7, 0, 0, 0, 0, 5 },
{ 0, 4, 0, 0, 0, 0, 0, 3, 0 },
{ 8, 0, 0, 0, 0, 6, 1, 0, 0 },
{ 6, 0, 0, 9, 0, 0, 0, 4, 1 },
{ 0, 9, 0, 6, 0, 0, 0, 8, 0 },
{ 0, 0, 0, 0, 2, 0, 0, 0, 0 }
};
int x, y;
for (x=0;x<9;x++)
for (y=0;y<9;y++)
if (board[x][y]==0) // 尋找空格
Sol[Cnt++] = (x<<8)+(y<<4);
printf( "\n數獨題目為 --\n" );
Show(board);
Promising(board, 0);
if (Ans==1) printf( "\n這是唯一解的標準數獨題目!!\n" );
else if (Ans==0) printf( "\n此題無解!!\n" );
else printf( "\n此題有 %d組多重解!!\n", Ans );
return 0;
}
// 顯示 --
void Show(int b[][9])
{
char num[] = " 123456789";
printf("╔═╤═╤═╦═╤═╤═╦═╤═╤═╗\n");
for(int x=0; x<9; x++)
{
for(int y=0; y<9; y++)
printf("%s %c", (y%3==0)? "║" :"│", num[b[x][y]]);
printf("║");
if (x==8)
printf("\n╚═╧═╧═╩═╧═╧═╩═╧═╧═╝\n");
else if (x%3==2)
printf("\n╠═╪═╪═╬═╪═╪═╬═╪═╪═╣\n");
else
printf("\n╟─┼─┼─╫─┼─┼─╫─┼─┼─╢\n");
}
}
//
int Tracking(int b[][9], int n)
{
int xx, yy, m, num, r;
int x = Sol[n]>>8;
int y = (Sol[n]>>4)&0x0F;
for(num=1, r=0; num<=9; num++)
{
b[x][y] = num;
Sol[n] = (Sol[n]&0xFF0) + num;
for(m=0; m<9; m++)
{
xx = x/3*3+m%3;
yy = y/3*3+m/3;
if ((m!=y && b[x][m]==b[x][y]) || (m!=x && b[m][y]==b[x][y])
|| (x!=xx && y!=yy && b[xx][yy]==b[x][y]))
break;
}
if (m==9 && Promising(b, n+1)) r=1;
}
// backtracking -- 回溯
b[x][y]=0;
Sol[n]&=0xFF0;
return r;
}
//
int Promising(int b[][9], int n)
{
if (n<Cnt) return Tracking(b, n);
//-- solution is found
if (++Ans<2) // 限制只顯示第一組解答
{
printf("\n得到第 %d組解答:\n", Ans);
Show(b);
printf("\nSolution :");
for(n=0; n<Cnt; n++)
printf( "%c[%d,%d]:%d ",(n%8==0)?'\n': ' ', (Sol[n]>>8)+1,
((Sol[n]>>4)&0x0F)+1, Sol[n]&0x0F );
printf("\n");
}
return 1;
}