期末報告
===
# 程式設計(使用C++)
## EX_01:輸入三角形三邊長,以海龍公式求三角形面積。先輸出s看看是否正確。(整數除法、浮點數除法)(先乘除後加減)
### 預設:
```cpp=
#include <iostream>
....... // 含入 cmath 標頭檔,才可使用sqrt
using namespace std;
int main()
{
........ // 宣告 a,b,c 三邊長變數為整數型態
double s, area;
........ // 以cout輸出提示字串
........ // 以cin輸入邊長變數
s = ........
area = ........
cout << "三角形面積為 " << area << endl; // a=5,b=6,c=7,area=14.6969
return 0;
}
```
### Ex_1 Ans:
```cpp=
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
int a,b,c;
double s,area;
cout << "請輸入三角形的三邊長:" << endl;
cin >> a >> b >> c;
s=(double)(a+b+c)/2;
area=sqrt(s*(s-a)*(s-b)*(s-c));
cout << "三角形面積為" << area << endl;
return 0;
}
```
* 1.整數運算會去掉小數
* 2.乘號不能省
## Ex_2:承EX_01,先判斷三邊長是否可以構成三角形。如果可以,求三角形面積;如果不行,輸出錯誤。
* 每邊長要大於0,且任兩邊之和要大於第三邊。
### 預設:
```cpp=
int main()
{
........ // 宣告 a,b,c 三邊長變數為整數型態
double s, area;
cout << "請輸入三邊長:";
cin >> a >> b >> c;
if ( a > 0 && ........ && a + b > c && ........ ) // if else 後不用加分號
{
s = ........
area = ........
cout << "三角形面積為 " << area << endl;
}
else // 不用加分號
{
cout << "不能構成三角形";
}
return 0;
}
```
### Ex_2 Ans:
```cpp=
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
int a,b,c;
double s,area;
cout << "請輸入三角形的三邊長:" << endl;
cin >> a >> b >> c;
if( a>0 && b>0 && c>0 && a+b>c && a+c>b && b+c>a )
{
s=(double)(a+b+c)/2;
area=sqrt(s*(s-a)*(s-b)*(s-c));
cout << "三角形面積為" << area << endl;
}
else
{
cout << "不能構成三角形";
}
return 0;
}
```
* if和else後方不用打分號
## Ex_3:驗證登入帳號、密碼
```cpp=
int main()
{
string user,pwd;
cout << "請輸入帳號:";
cin >> user;
........ // 讓使用者輸入密碼
........
if (user=="admin" && ........)
{
cout << "Welcome";
}
else
{
........ // 不等於!=
{
cout << "帳號錯誤";
}
........
{
cout << "密碼錯誤";
}
}
// Q:帳號、密碼都錯時會顯示?如何顯示帳號錯誤,密碼錯誤?
return 0;
}
```
### Ex_3 Ans
```cpp=
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
string user,pwd;
cout << "請輸入帳號:";
cin >> user;
cout << "請輸入密碼:";
cin >> pwd;
if( user=="500207" && pwd=="030030" )
{
cout << "Welcome";
}
else
{
if(user!="500207" && pwd!="030030")
{
cout << "帳號及密碼錯誤";
}
else
{
if(user!="500207")
{
cout << "帳號錯誤";
}
if(pwd!="030030")
{
cout << "密碼錯誤";
}
}
};
return 0;
}
```
## Ex_5:印出 10 個 “hello”
```cpp=
int main()
{
int i; // 區域變數 vs. 區塊變數 for (int i=1;i<=10;i++)
for (i=1;i<=10;i=i+1) // 讓 i 從 1~10。for()後面不可加分號
{
cout << "hello ";
}
cout << i; // Q:i 會顯示多少?
}
/*
i=i+1
i+=1
i++
*/
```
## Ex_6:聖誕樹
```cpp=
int main()
{
int n;
cout << "請輸入n:";
cin >> n;
for ........ // 總共n列
{
for ........ // 每列印星號之前先印「空白」
{
cout << " ";
}
for (int j=1;j<= .... ;j++) // 星號的數量和列編號有關(1,3,5,7,9...)
{
cout << "*";
}
........ // 印完一列要換行
}
return 0;
}
```
## Ex_6
```cpp=
#include <iostream>
using namespace std;
int main()
{
int n,sum=1;
for(int j=1;j<=2*i-1;j++)
{
cout << "*";
}
cout << endl;
}
for(int i=1;i<=n/2;i++)
{
for(int j=1;j<=2*n/3;j++)
{
cout << " ";
}
for(int j=1;j<=2*n/3;j++)
{
cout << "*";
}
cout << endl;
}
return 0;
}
```
## Ex_7:while 存錢買手機
```cpp=
int main()
{
int i=1, ......... ;
while ........
{
cout << "請輸入第 " << i << " 個月的存款: ";
cin >> money;
........ // 把 money 加到 sum
........ // i+1
}
cout << "存了 " << .... << " 個月,總共 " << sum;
return 0;
}
```
### Ex_7 Ans
```cpp=
#include <iostream>
using namespace std;
int main()
{
int i=1,sum=0,money;
while(sum<100000)
{
cout << "輸入第" << i << "個月的存款:";
cin >> money;
sum+=money;
i++;
}
cout << "存了" << i-1 << "個月";
return 0;
```
## Ex_8:小算盤開根號(以二分搜尋法實作)
```cpp=
int main()
{
int n;
bool sol=false;
cin >> n;
for ........ // 只需檢測到 n/2
{
if ........ // 如果i的平方等於n
{
cout << i;
........ // sol 設為 true,表示找到根
........ // 跳出迴圈
}
}
if ........ // 沒有解,! -> not
{
cout << "只能求完全平方數的平方根!";
}
return 0;
}
```
### Ex_8 Ans
```cpp=
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
double a,n;
int cnt=0;
cin >> n;
a=n;
do
{
a=(a*a+n)/(2*a);
cnt++;
}while(a*a-n > 1e-13);
printf("經過了 %d 次運算,根號 %f 為 %.13f", cnt,n,a);
return 0;
}
```
## Ex_9:小算盤開根號(以二分搜尋法實作)
```cpp=
int main()
{
double n,lower,upper,mid;
// Q2
cin >> n;
lower = 1;
upper = n-1;
while ........ // 上下界限的差 > 10^-13(數學寫法),就繼續逼進
{
mid = ........ // mid 為上下界限的中間
// Q2
if ( mid*mid > n ) // 如果中間數的平方 > n,解在lower~mid間
........ // 將上限調為 mid
else if ........ // 如果中間數的平方 < n,解在mid~upper間
........ // 將下限調為 mid
else
break;
}
printf("%.13f",mid); // 需含入標頭檔 cstdio
return 0;
}
Q1:2不行?
Q2:新增一個整數變數cnt,記錄總共做了幾次運算得解
printf("經過了 %d 次運算,根號 %f 為 %.13f", cnt,n,mid);
```
### EX_9 Ans
```cpp=
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
int n=5000000;
for (int i=2;i<=n;i++)
{
bool prime=true;
for (int j=2;j<sqrt(i);j++)
{
if (i%j==0)
{
prime==false;
break;
}
}
//if (prime)
//cout << i << " ";
}
return 0;
}
```
## Ex_10 埃拉托斯特尼篩法(課本p3-5),求1億以內的質數
```cpp=
int main()
{
int n=100000000;
bool isPrime[100000001]; // 區域變數只能到200萬左右,改為全域變數。
fill(isPrime,isPrime+n+1,1); // 全部先設為1(true),假設都是質數。需含入algorithm標頭檔
isPrime[1]=false; // 1不為質數
for (int i=2;i<=sqrt(n);i++) // 檢查到<=√n即可
if ........ // 如果i是質數
for ........ // 如果i是質數,則篩掉它的倍數。(從i^2開始,每次+i)
isPrime[....]=....; // i的倍數不為質數
for (int i=1;i<=n;i++)
if (isPrime[i])
cout << i << " ";
return 0;
}
```
### Ex_10 Ans
```cpp=
#include <iostream>
#include <cmath>
using namespace std;
bool isPrime[100000001];
int main()
{
int n=100;
fill(isPrime,isPrime+n+1,1);
isPrime[1]=false;
for (int i=2;i<=sqrt(n);i++)
if (isPrime[i])
for(int j=i*i;j<=n;j+=i)
isPrime[j]=false;
for (int i=1;i<=n;i++)
if (isPrime[i])
cout << i << " ";
return 0;
}
```
## Ex_11_1:大樂透電腦選號
```cpp=
int main()
{
........ // 宣告一個大小6的num陣列
srand(5); // 設定亂數種子。srand(time(NULL)); 需含入標頭檔 ctime
for ........ // 陣列的索引值由0開始,所以i初值要設為0
{
num[....] = rand()....; // 隨機產生1~49間的數,需含入標頭檔 cstdlib
}
for ........ // 印出陣列裏的亂數
{
cout << num[....] << " ";
}
return 0;
}
```
### Ex_11_1 Ans
```cpp=
#include <iostream>
#include <cmath>
using namespace std;
int dc(int b,int p,int m)
{
if (p==1)
return b%m;
else
{
int half=dc(b,p/2,m);
if (p%2==0)
return half*half%m;
else
return half*half*b%m;
}
}
int main()
{
int b,p,m;
while(cin >> b >> p >> m)
cout << dc(b,p,m) << endl;
return 0;
}
```
## Ex_11_2:大樂透電腦選號(解決數字重覆的問題)
```cpp=
int main()
{
int num[6]; // 宣告一個大小6的num陣列
int mark[50]={0}; // 標記陣列的初值=0。50個空間,陣列索引值為0~49
int t;
srand(5); // 設定亂數種子。srand(time(NULL)); 需含入標頭檔 ctime
for (int i=0;i<6;i++) // 陣列的索引值由0開始,所以i初值為0
{
do
{
t = rand()%49+1; // 隨機產生1~49間的數,暫放於t
} while ........ // 如果mark陣列第t個位子為1,代表亂數重覆,再產生另一個亂數
........ // 將產生的不重覆亂數記錄在num陣列
........ // 將mark陣列第t個位子的值設為1,表示產生過t這個數字
}
for (int i=0;i<6;i++) // 印出陣列裏的亂數
{
cout << num[i] << " ";
}
return 0;
}
Q1:產生亂數後,檢查此數字是否重覆,如果重覆再產生一次,下列程式碼想法有何漏洞?
for(int i=0;i<6;i++)
{
t=rand()%49+1;
for (int j=0;j<i;j++)
if (t==num[j])
t=rand()%49+1;
num[i]=t;
}
Q2:t=rand()%5+1會發生什麼狀況?(陣列除錯練習)
```
### Ex_11_2 Ans
```cpp=
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
int main()
{
int num[6],t;
int mark[50]={0};
srand(time(NULL));
for(int i=0;i<6;i++)
{
do
{
t=rand()%49+1;
}while(mark[t]==1);
num[i]=t;
mark[t]=1;
}
for(int i=0;i<5;i++)
{
for(int j=0;j<5-i;j++)
{
if(num[j]>num[j+1])
{
t=num[j];
num[j]=num[j+1];
num[j+1]=t;
}
}
}
for(int i=0;i<6;i++)
{
cout << num[i] << " ";
}
return 0;
}
```
## Ex_12:求學測總級分和平均
```cpp=
int main()
{
int score[4][7] = {{12,13,15,10,12,0,0},{15,13,15,15,14,0,0},{14,14,12,15,13,0,0},{11,10,12,12,10,0,0}},sum=0;
for ........ // 4個人,列
{
........ // 計算每人總分之前,sum 要先歸0
for ........ // 5科,欄
{
sum += score[....][....];
}
score[....][5] = sum;
score[....][....] = sum/5;
}
cout << "座號\t國文\t英文\t數學\t自然\t社會\t總分\t平均\n";
for (int i=0;i<4;i++)
{
........ // 先印出座號
for (int j=0;j<....;j++)
{
cout << score[i][j] << "\t";
}
cout << endl;
}
return 0;
}
```
### Ex_12 Ans
```cpp=
#include <iostream>
using namespace std;
int main()
{
int score[4][8] ={{12,13,15,10,12,0,0,0},
{15,13,15,15,14,0,0,0},
{14,14,12,15,13,0,0,0},
{11,10,12,12,10,0,0,0}};
for(int i=0;i<4;i++)
{
int sum=0;
for(int j=0;j<5;j++)
sum += score[i][j];
score[i][5] = sum;
score[i][6] = sum/5;
}
for(int i=0;i<4;i++)
{
int p=0;
for(int j=0;j<4;j++)
{
if(score[i][5] < score[j][5])p++;
}
score[i][7]=p+1;
}
cout << "座號\t國文\t英文\t數學\t自然\t社會\t總分\t平均\t名次\n";
for (int i=0;i<4;i++)
{
cout << i+1 << "\t";
for (int j=0;j<8;j++)
{
cout << score[i][j] << "\t";
}
cout << endl;
}
return 0;
}
```
## EX_13:ZeroJudge b112: 5. 高中運動會。
#### 以輾轉相除法求兩數的最大公因數(寫成函式),並用之來求4數的最大公因數
```cpp=
#include <iostream>
using namespace std;
int gcd(int a,int b)
{
int r;
do
{
r=a%b;
a=b;
b=r;
}while(r!=0);
return a;
}
int main()
{
int a=400, b=200, c=150, d=625, g;
g = gcd(a,b);
g = gcd(g,c);
g = gcd(g,d);
cout << g;
return 0;
}
```
### Ex_13 Ans
```cpp=
#include <iostream>
using namespace std;
int gcd(int a,int b)
{
int r;
do
{
r=a%b;
a=b;
b=r;
}while(r!=0);
return a;
}
int main()
{
int a=400, b=200, c=150, d=625, g;
g = gcd(a,b);
g = gcd(g,c);
g = gcd(g,d);
cout << g;
return 0;
}
```
## 演算法
### EX_06_2:ZeroJudge c129: 00572 - Oil Deposits
```cpp=
#include <iostream>
using namespace std;
int visited[100][100]={0};
char mp[100][100];
int r,c;
void dfs(int i,int j)
{
if(i<0 || i>=r || j<0 || j>=c || visited[i][j]==1 || mp[i][j]=='*')
return;
visited[i][j]=1;
dfs(i-1,j-1);
dfs(i-1,j);
dfs(i-1,j+1);
dfs(i,j-1);
dfs(i,j+1);
dfs(i+1,j-1);
dfs(i+1,j);
dfs(i+1,j+1);
}
int main()
{
while(cin >> r >> c && r!=0 && c!=0)
{
int cnt=0;
for(int i=0;i<r;i++)
for(int j=0;j<c;j++)
{
cin >> mp[i][j];
visited[i][j]=0;
}
for(int i=0;i<r;i++)
{
for(int j=0;j<c;j++)
{
if(mp[i][j]=='@' && visited[i][j]==0)
{
dfs(i,j);
cnt++;
}
}
}
cout << cnt << endl;
}
return 0;
}
```
* ???????????????????????