#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
*/
趣学算法