#include<cstdio>
#include<iostream>
#include<bits/stdc++.h>
#define N 1001
using namespace std;
int Num = 0;
double ans;
int binarySearch( const int b[], int searchKey, int low, int high ) {
int middle;
while( low <= high ) {
middle = ( low + high ) / 2;
if (searchKey == b[middle]) {
Num++;
return middle;
}
else if ( searchKey < b[middle] ) {
high = middle - 1;
Num++;
}
else {
low = middle + 1;
Num++;
}
}
return -1; // not found
}
int main()
{
int arr[N];
cout << "元素的個數" << setw(18) << "理論平均查找次數" << setw(22) << "實際平均查找次數" << endl;
for ( int j=100; j <=1000; j+=100 )
{
Num = 0;
arr[0]=10+rand()%15;
for(int i=1; i<j; i++) {
// 生成遞增隨機數列
arr[i]=arr[i-1]+1+rand()%3+rand()%10;
}
int SearchTimes = 10;
for (int time=0; time < SearchTimes; time++)
{
int index = rand() % j; // suffix 爲要搜索的元素下標
int key = arr[index]; // key 爲要查找的數據
int result = binarySearch(arr, key, 0, j-1 );
}
ans = (double)(Num) / SearchTimes;
cout << setw(6) << j << setw(18) << int( log(j)/log(2) )+0.5<< setw(22) <<ans << endl;
}
return 0;
}
#include<bits/stdc++.h>
#define N 101
using namespace std;
int n,w[N],v[N],W;//n個物品,重量存在w數組,價值存在v數組,揹包容量爲W
int c[N][N] = {0},x[N];//c[i][j]表示前i個物品放在容量爲j的揹包獲得的最大價值,x[i]表示第i個物品是否放入揹包
void compute()
{
int i,j;
for(i = 1;i <= n;i++)
for(j = 1;j<= W;j++)
{
if(j < w[i])//物品重量大於揹包容量則不放
c[i][j] = c[i-1][j];
else //能放,則判斷放還是不放能使價值最大化
c[i][j] = max(c[i-1][j],c[i-1][j-w[i]]+v[i]);
}
j = W;//回退判斷哪些物品放進去了
for(i = n;i > 0;i--)
{
if(c[i][j] >c[i-1][j])
{
x[i] = 1;
j -= w[i];
}
else
x[i] = 0;
}
cout << "放入揹包的有:"<<endl;
for(i = 1;i <= n;i++)
if(x[i])
cout <<i<<" ";
cout << endl;
}
int main()
{
cout <<"請輸入物品數和揹包容量:"<<endl;
cin >> n >> W;
cout <<"請依次輸入每個物品的重量和價值:"<<endl;
for(int i = 1;i <= n;i++)
cin >> w[i] >> v[i];
compute();
return 0;
}
/*測試數據
5 10
2 6 5 3 4 5 2 4 3 6
*/
#include <iostream>
#define N 1024
using namespace std;
int BOARD_SZ;
static int tile = 1;
static int board[N][N] = {0};
void chess_board(int tr, int tc, int dr, int dc, int size)
{
if(size == 1)
return;
int t = tile++;
int sz = size / 2; //每次進行劃分
if(dr < tr+sz && dc < tc+sz) //注意一共四種情況,<>=這幾個符號要控制好邊界
chess_board(tr, tc, dr, dc, sz);
else{
board[tr+sz-1][tc+sz-1] = t;
chess_board(tr, tc, tr+sz-1, tc+sz-1, sz);
}
if(dr < tr+sz && dc >= tc+sz) //notice < >=
chess_board(tr, tc+sz, dr, dc, sz);
else{
board[tr+sz-1][tc+sz] = t;
chess_board(tr, tc+sz, tr+sz-1, tc+sz, sz);
}
if(dr >= tr+sz && dc < tc+sz) //notice >= <
chess_board(tr+sz, tc, dr, dc, sz);
else{
board[tr+sz][tc+sz-1] = t;
chess_board(tr+sz, tc, tr+sz, tc+sz-1, sz);
}
if(dr >= tr+sz && dc >= tc+sz) //notice >= >=
chess_board(tr+sz, tc+sz, dr, dc, sz);
else{
board[tr+sz][tc+sz] = t; //標記一個假設的特殊點
chess_board(tr+sz, tc+sz, tr+sz, tc+sz, sz); //遞歸該部分
}
}
void print_chess_board()
{
cout.setf(ios::left); //左對齊
for(int i=0; i<BOARD_SZ; ++i){
for(int j=0; j<BOARD_SZ; ++j){
cout.width(3); //打印寬度爲3
cout<<board[i][j];
}
cout<<endl;
}
}
int main()
{
int dr,dc;
cout << "請輸入特殊方格的行列號和規格:"<<endl;
cin >> dr >> dc >> BOARD_SZ;
chess_board(0, 0, dr, dc, BOARD_SZ);
print_chess_board();
return 0;
}
//F[k,x]表示處理完第k個作業且A機器到達了時間x,B機器到達的最小時間,
//處理完第i個作業,如果是A處理的那麼F[i,x+a[i]] = b[i-1]
//否則F[i,x] =f[i-1,x]+ b[i]
#include<bits/stdc++.h>
#define N 1001
using namespace std;
int n,a[N] = {0},b[N] = {0},F[N][N] = {0},sumA = 0;//n個作業
void init()
{
cout << "請輸入作業的個數: ";
cin >> n;
cout <<"請輸入作業在機器A上的時間:"<<endl;
for(int i = 1;i <= n;i++)
{
cin >> a[i];
sumA += a[i];
}
cout <<"請輸入作業在機器B上的時間:"<<endl;
for(int i = 1;i <= n;i++)
cin >> b[i];
}
void solve()
{
for(int i = 1;i <= n;i++)
{
for(int j = 0;j <= sumA;j++)
{
if(j >= a[i])
F[i][j] = min(F[i-1][j-a[i]],F[i-1][j]+b[i]);
else
F[i][j] = F[i-1][j] + b[i];
}
}
}
void print()
{
int temp = 0,minv = 99999;
for(int j = 0;j <= sumA;j++)//
{
temp = max(F[n][j],j);
if(minv > temp)
minv = temp;
}
cout<<"最小完成時間爲:"<<endl;
cout << minv;
}
int main()
{
init();
solve();
print();
return 0;
}
/*
6
2 5 7 10 5 2
3 8 4 11 3 4
*/
#include <iostream>
#include <queue>
using namespace std;
int bit[100] = {0};//用於存儲遞歸調用時的編碼
class Node{
public:
int id;//在數組中的索引
int parent;
int lchild;
int rchild;
float weight;//權重,即字符的出現頻率
char value;
//缺省構造函數,確定成員的初始值
Node():id(-1),parent(-1),lchild(-1),rchild(-1),weight(0),value(' '){}
void setValue(int _id,int _lchild, int _rchild, float _weight)
{
id = _id;
//parent = _parent;
lchild = _lchild;
rchild = _rchild;
weight = _weight;
}
//重寫 < 運算符,使其能夠在優先隊列中正確的排序
bool operator<(const Node &a)const
{
return a.weight < weight;
}
};
int n,k;
Node* haff;//一個指向Node型數組的指針
priority_queue<Node> pq;//存儲節點的優先隊列
vector<Node> v;
void init()
{
char c;
float f;
cout<<"請輸入字符的個數:"<<endl;
cin >> n;
k = n;
haff = new Node[n+n+2];
cout<<"請依次輸入字符值和頻率"<<endl;
for(int i = 1;i<= n;i++)
{
cin >>c>>f;
haff[i].value = c;
haff[i].weight = f;
haff[i].id = i;
pq.push(haff[i]);
}
}
void bulidHaff()
{
while(pq.size() > 1)
{
Node a,b,c;
a = pq.top();
pq.pop();
b = pq.top();//取出權值最小的兩棵子樹合併成新的子樹
pq.pop();
k++;
//計算新和成的子樹的權重等,並放到數組中,方便確定編碼方式
haff[k].setValue(k,a.id,b.id,a.weight+b.weight);//爲什麼直接++k不行?
pq.push(haff[k]);//新樹插入到優先隊列中
}
}
void dfs(Node h,int num)
{
if(h.value >= 97 && h.value <= 122)
{
cout<<"字符 "<<h.value<<" 的編碼爲:";
for(int i = 0;i < num;i++)
cout<<bit[i];
cout<<endl;
return ;
}
else//右子樹編碼爲1,左子樹編碼爲0
{
if(h.rchild != -1)
{
dfs(haff[h.rchild],num+1);
bit[num] = 1;
}
if(h.lchild != -1)
{
dfs(haff[h.lchild],num+1);
bit[num] = 0;
}
}
}
int main()
{
init();
bulidHaff();
dfs(pq.top(),0);//遞歸調用求出字符的編碼
return 0;
}
/*測試數據
6
a 0.05
b 0.32
c 0.18
d 0.07
e 0.25
f 0.13
*/
#include<bits/stdc++.h>
#define N 1001
using namespace std;
//dis數組存儲加油站之間的距離,sum[i]表示存儲第一個到第i個加油站間的總距離
int dis[N] = {0},n,k,sum[N] = {0};
bool flag = true;//表示是否能達到終點
int station = 0;//停靠的次數
void init()
{
cout<<"請輸入汽車滿油最大行駛距離和加油站的數量:"<<endl;
cin >> n >> k;
cout<<"請依次輸入加油站之間短距離:"<<endl;
for(int i = 1;i <=k+1;i++)
{
cin >> dis[i];
sum[i] = sum[i-1]+dis[i];
if(sum[i] - sum[i-1] > n)//如果有兩個相鄰加油站之間距離大於n,則不可能到達終點
flag = false;
}
}
void greedy()
{
if(!flag)
{
cout<<"Sorry,No Solution!"<<endl;
return ;
}
//start代表上一次的停靠點,stop代表本次將要停靠的點
int start = 0,stop;
cout<<"停靠的加油站有:"<<endl;
for(stop = 1;stop < k+2;stop++)
{
//貪心選擇一個剛好汽車行駛最大距離能達到的加油站
if(sum[stop] - sum[start] <= n && sum[stop+1] - sum[start] > n)
{
station++;
start = stop;
cout <<stop<<" ";
}
//最後一站是終點,停車不加油,正好sum[k+2]等於0,station不會加
}
cout << k+1<<endl;
}
int main()
{
init();
greedy();
cout<<"最少加油的次數是: "<<station<<endl;
for(int i = 1;i <= k+1;i++)
cout<<sum[i]<<" ";
return 0;
}
/*測試數據
7 7
1 2 3 4 5 1 6 6
*/
//圖的m着色問題
#include<bits/stdc++.h>
#define N 101
using namespace std;
int n,color,bian,m[N];//節點數,顏色數,和邊的條數,m[i]表示第i個節點的顏色
int pict[N][N] = {0},ans = 0;//圖的鄰接矩陣
void init()
{
cin >> n >> color >> bian;
for(int i = 1;i <= bian;i++)
{
int a,b;
cin >>a >> b;
pict[a][b] = 1;
pict[b][a] = 1;
}
}
bool ok(int k)
{
for(int j = 1;j < k;j++)
{
if(pict[k][j] && m[k] == m[j])
return false;
}
return true;
}
void backtrack(int k)
{
if(k > n)
{
cout << "第" << ++ans << "種方案:" << endl;
for(int i = 1;i <= n;i++)
cout << m[i] << " ";
cout << endl;
return ;
}
for(int c = 1; c <= color; c++)
{
m[k] = c;
if(ok(k))
backtrack(k+1);
//回退時m[k]不影響前面的取值,所以不需要改回去
}
}
int main()
{
init();
backtrack(1);
return 0;
}
/*測試數據
7 3 12
1 2
1 3
1 4
2 3
2 5
3 4
3 5
4 5
4 7
5 6
5 7
6 7
*/
//0-1揹包問題的回溯算法實現
#include<bits/stdc++.h>
#define N 1001
using namespace std;
int n,w[N] = {0},v[N] = {0};//n見物品,第i件物品重量爲w[i],價值爲v[i]
int cw = 0,cv = 0,we,bestv = 0;//cw表示已經放入揹包的重量,cv表示已經放入揹包的價值,we表示揹包的容量,bestw表示最優值即最大價值
int x[N],best[N];//x表示回溯過程中的解,best記錄最優的解,1爲放入,0不放
void init()
{
cout << "請輸入物品數量和揹包容量,用空格分開:" <<endl;
cin >> n >> we;
cout << "請依次輸入 " << n << " 件物品的重量和價值,用空格分開:"<<endl;
for(int i = 1;i <= n;i++)
{
cin >> w[i] >> v[i];
}
}
int Bound(int k)//上界函數,返回已放入的物品價值和剩下的價值和
{
int sum = 0;
for(int i = k;i <= n;i++)
sum += v[i];
return (cv + sum);
}
void backTrack(int k)//代表第k層
{
if(k > n)//一直搞不懂爲什麼到了最後一層就一定是最優解,不用判斷以前的bestv和本次bestv哪個大嗎,仔細一想,能到達最後一層的情況要麼n件物品全部放入,(不滿足限界條件就剪紙了,到不了最後)
{ //肯定是最大值;要麼也是滿足限界函數Bound(k+1) > bestv才能到達最後一層,所以肯定比上次的bestv大
int sum = 0;
for(int j = 1;j <= n;j++)
{
best[j] = x[j];
sum += (x[j] * v[j]);
}
bestv = sum;
return ;
}
if(cw + w[k] < we)//滿足約束條件,即還能放入第k個物品,搜索左子樹
{
x[k] = 1;
cw += w[k];
cv += v[k];
cout << "cv: " << cv << endl;
backTrack(k+1);
cw -= v[k];
cv -= v[k];
}
if(Bound(k+1) > bestv)//第k個揹包不放入,如果滿足上界函數也有可能得到最優解,擴展右子樹
{
x[k] = 0;
backTrack(k+1);
}
}
void print()
{
cout << "最優裝包價值爲:"<<bestv<<endl;
cout << "裝進揹包的物品編號爲:" << endl;
for(int i = 1;i <= n;i++)
if(best[i])
cout << i << " ";
}
int main()
{
init();
backTrack(1);//從第一個揹包開始判斷
print();
return 0;
}
/*測試數據
5 10
2 6 5 3 4 5 2 4 3 6
*/
#include<bits/stdc++.h>
#define INF 9999
#define N 1001
using namespace std;
int n, m;
int g[N][N], x[N], best[N];//城市的鄰接矩陣,路線的臨時保存,最優路線
int c = 0, bestl = INF;//目前經過城市的路徑和,最優路徑和
void init()
{
cout << "請輸入城市數和邊數:";
cin >> n >> m;
for(int i = 1;i <= n;i++)
{
x[i] = i;
for(int j = 1;j <= n;j++)
g[i][j] = INF;
}
cout << "請依次輸入兩個相連城市的編號和距離:" << endl;
for(int i = 1;i <= m;i++)
{
int x1,x2,x3;
cin >> x1 >> x2 >> x3;
g[x1][x2] = g[x2][x1] = x3;
}
}
void travel(int k)
{
if(k > n)
{
if(g[x[n]][1] != INF && c+g[x[n]][1] < bestl)//最後一個節點和第一個節點有通路且,加上最後一段距離小於目前最優長度
{
bestl = c+g[x[n]][1];
for(int i = 1;i <= n;i++)
best[i] = x[i];
return ;
}
}
else
{
for(int j = k;j <= n;j++)
{
//有通路且可能產生最優解
if(g[x[k-1]][x[j]] != INF && c + g[x[k-1]][x[j]] < bestl)
{
swap(x[k],x[j]);
c += g[x[k-1]][x[k]];
travel(k+1);
c -= g[x[k-1]][x[k]];
swap(x[k],x[j]);
}
}
}
}
void print()
{
cout <<"最短路徑爲: " << bestl << endl << "路線是:" <<endl;;
for(int i = 1;i <= n;i++)
cout << best[i] << "->";
cout << "1"<< endl;
}
int main()
{
init();
travel(2);
print();
return 0;
}
/*測試數據
5 9
1 2 3
1 4 8
1 5 9
2 3 3
2 4 10
2 5 5
3 4 4
3 5 3
4 5 20
*/
趣學算法