一、找零钱
根据实际情况,有1元、(2元的已经不流通了)、5元、10元、20元、50元、100元。当有人给出36524元时,如何找钱给对方。
// 找钱的类
class payMoney
{
public:
payMoney();
~payMoney();
int howManyCash(int waitToPay);
private:
int *arr;
};
// 初始化钱的种类
payMoney::payMoney()
{
arr= new int[6];
arr[0] = 100;
arr[1] = 50;
arr[2] = 20;
arr[3] = 10;
arr[4] = 5;
arr[5] = 1;
}
// 析构
payMoney::~payMoney()
{
delete [] arr;
}
// 找钱函数
// inparam: 等待找钱
// outparam: 总共需要多少张钱
int payMoney::howManyCash(int waitToPay)
{
int count = 0; // 用于记录总共需要钱的数量
int num = 0;
for (int i = 0; i < 6; ++i)
{
num = waitToPay/arr[i]; // 优先找面值较大的钱,需要的张数
if (num >= 1)
{
count += num;
cout << "need " << num << " " << arr[i] << "RMB" << endl;
waitToPay -= num * arr[i];
}
}
cout << "total need " << count <<" RMB." << endl;
return count;
}
int main()
{
// payRMN:
payMoney pmoney;
cout << "please input need to pay monay: " << endl;
int money;
cin >> money;
if (money > 65535)
{
cout << "Illegal input!!!"<<endl;
}
else
{
pmoney.howManyCash(money);
}
return 0;
}
注意:如果对于有币种:100,99,1。当需要找396元时,贪心的结果是需要3张100,99张1元。但实际上,只需要4张99元,即可。
二、装豆子
#include<iostream>
using namespace std;
void swap(int &a, int &b)
{
int temp;
temp = a;
a = b;
b = temp;
}
void swap(char &c1, char &c2)
{
char temp;
temp = c1;
c1 = c2;
c2 = temp;
}
void compute(int *wei, int *total, int *single, int len)
{
for(int i = 0; i < len; ++i)
{
single[i] = total[i]/wei[i];
}
}
void sortSmallBig(int *wei, int *total, int *single, char *b, int len)
{
bool flag = true;
for(int i = 0; i < len - 1; ++i)
{
flag = true;
for(int j = 0; j < len - i - 1; ++j)
{
if(single[j] > single[j + 1])
{
swap(single[j], single[j + 1]);
swap(wei[j], wei[j + 1]);
swap(total[j], total[j + 1]);
swap(b[j], b[j + 1]);
flag = false;
}
}
if(flag)
break;
}
}
void print(int *arr, int len)
{
for(int i = 0; i < len; ++i)
{
cout << arr[i] << ", ";
}
cout << endl;
}
void print(char *c, int len)
{
for(int i = 0; i < len; ++i)
{
cout << c[i] << ", ";
}
cout << endl;
}
void putInBag(int *wei, int *single, int len, char *b, int need)
{
while(need > 0)
{
for(int i = len - 1; i >= 0; --i)
{
if(need >= wei[i])
{
need -= wei[i];
cout << "need " << b[i] << " bean" << wei[i] << " kg" << endl;
}
else if(need > 0)
{
cout << "need " << b[i] << " bean" << need << " kg" << endl;
need = 0;
}
else
break;
}
}
}
int main()
{
int weight[5] = {100, 30, 60, 20, 50};
int totalVal[5] = {100, 90, 120, 80, 75};
int singleVal[5] = {0,0,0,0,0};
char bean[5] = {'y', 'g', 'r', 'b', 'q'};
compute(weight, totalVal, singleVal, 5); // 计算单价
sortSmallBig(weight, totalVal, singleVal, bean, 5); // 排序
cout << "输出排序后的重量: " << endl;
print(weight, 5);
cout << "输出排序后的总价: " << endl;
print(totalVal, 5);
cout << "输出排序后的单价: " << endl;
print(singleVal, 5);
cout << "输出豆子种类:b-黑豆,g-绿豆,q-青豆,r-红豆,y-黄豆"<< endl;
print(bean, 5);
cout << "输出需要的哪种豆子,多少千克。" << endl;
putInBag(weight, singleVal, 5, bean, 100);
return 0;
}
三、分糖果
把糖果大小和孩子的需求,从小到大排序,优先满足需求小的孩子。由于满足一个需求大的孩子和满足一个需求小的孩子,对最终的期望值贡献是一样的,所以也可以都按照从大到小开始匹配。
以下例子从小到大开始匹配。
// 分糖果的类
class candyDistribute
{
public:
candyDistribute();
~candyDistribute();
void distribute(int *kid, int kidnum, int *candy, int candynum);
void print(int *arr, int len);
private:
void sortSmallBig(int *arr, int len);
};
candyDistribute::candyDistribute()
{
}
candyDistribute::~candyDistribute()
{
}
// 把孩子的需求和糖果的大小按照从小到大的顺序排列
void candyDistribute::sortSmallBig(int *arr, int len)
{
int preIndex, current;
for (int i = 1; i < len; ++i)
{
preIndex = i - 1;
current = arr[i];
while(preIndex >= 0 && arr[preIndex] > current)
{
arr[preIndex +1] = arr[preIndex];
--preIndex;
}
arr[preIndex + 1] = current;
}
}
// 打印输出,用于测试。
void candyDistribute::print(int *arr, int len)
{
for (int i = 0; i < len; ++i)
{
cout << arr[i] << " ";
}
cout << endl;
}
// inparam: 孩子的数组,和糖果的数组
void candyDistribute::distribute(int *kid, int kidnum, int *candy, int candynum)
{
sortSmallBig(kid, kidnum);
sortSmallBig(candy, candynum);
int kidcurrent = 0; // 当前第几个孩子
int candycurrent = 0; // 当前第几个糖果
while (kidcurrent < kidnum && candycurrent < candynum) // 糖果和孩子均没有匹配完
{
if (kid[kidcurrent] <= candy[candycurrent])
{
cout << " kid " << kid[kidcurrent] << " match " << " candy " << candy[candycurrent] << endl;
++kidcurrent;
++candycurrent;
}
else
{
++candycurrent;
}
}
if (kidcurrent == kidnum)
{
cout << "perfect! every kid own a candy." << endl;
}
else
{
cout << "just satisfy " << kidcurrent << " kids!" << endl;
}
}
int main()
{
candyDistribute candyD;
int kid[] = {5,10,2,9,15,9,10};
int candy[] = {6,1,20,3,8,12,18};
cout << "kid need: "<< endl; // 排序前孩子的需求
candyD.print(kid, 7);
cout << "canny weight:" <<endl; // 排序前糖果的大小
candyD.print(candy,7);
cout << "kid match candy;" << endl; // 孩子需求和糖果匹配
candyD.distribute(kid,7,candy,6);
cout << "kid need sort : "<< endl; // 输出,查看排序是否正确
candyD.print(kid, 7);
cout << "canny weight sort :" <<endl; // 输出,查看排序是否正确
candyD.print(candy,7);
return 0;
}
四、区间覆盖
4.1 以第一个数据为起始点,找出不连续的一组数据。代码如下:
#include<iostream>
using namespace std;
// 交换函数,用于排序
void swap(int &a, int &b)
{
int temp = 0;
temp = a;
a = b;
b = temp;
}
// 把区间数据,按照开始位置,由小到大排序
// 两个数组长度相同
void sortSmallBig(int *arrmin, int *arrmax, int len)
{
bool flag = true;
for(int i = 0; i < len - 1; ++i)
{
flag = true;
for(int j = 0; j < len - i - 1; ++j)
{
if(arrmin[j] > arrmin[j + 1])
{
swap(arrmin[j], arrmin[j + 1]); // 交换起始点
swap(arrmax[j], arrmax[j + 1]); // 交换结束点
flag = false;
}
}
if(flag)
break;
}
}
// 查找区域不想交的点,然后标记索引
void Coverage(int *arrmin, int *arrmax, int len, char *c)
{
sortSmallBig(arrmin, arrmax, len);
c[0] = '1';
int index = 0;
for(int i = 1; i < len; ++i)
{
if(arrmin[i] >= arrmax[index])
{
c[i] = '1';
index = i;
}
}
}
// 输出所有不想交的区间
void print(int *arrmin, int *arrmax, char *c, int len)
{
for(int i = 0; i < len; ++i)
{
if(c[i]=='1')
{
cout << "start: " << arrmin[i] << " end: " << arrmax[i] << endl;
}
}
}
// 测试
int main()
{
int Imin[6] = {0,2,3,1,5,8};
int Imax[6] = {3,4,5,5,9,10};
char c[6] = {'0','0','0','0','0','0'}; // 用于记录被选中的区间的索引
Coverage(Imin, Imax, 6, c);
print(Imin, Imax, c, 6);
return 0;
}
4.2 查找所有区间不想交的点。
五、霍夫曼编码
#include <iostream>
#include <stdlib.h>
#include <vector>
#include <queue>
#include <string>
#include <algorithm>
#include <memory.h>
#define N 6
typedef unsigned int UINT;
using namespace std;
typedef struct HFMnode
{
char data;
char code;
UINT weight;
HFMnode *parent, *lp, *rp;
HFMnode()
{
data = '/';
code = '0';
weight = 0;
parent = lp = rp = NULL;
}
}HFMnode;
class comp
{
public:
bool operator()(HFMnode* &a, HFMnode* &b)const
{
if (a->weight == b->weight)
{
return a->data > b->data;
}
return a->weight > b->weight;
}
};
class HuffmanTree
{
public:
HFMnode *root; // 根结点指针
HFMnode *node[2*N-1]; // N个字符,霍夫曼树结点个数2*n-1
priority_queue<HFMnode*, vector<HFMnode*>, comp> pri_queue; // 插入的同时,进行排序。按照权重从大到小
// 优先队列中存放类指针时,第三个参数应该另写一个comp类,类内写operator()
void creatTree_outputCode(int *w)
{
char ch = 'a';
HFMnode *left, *right;
for (int i = 0; i < N; ++i, ++ch) // 把abcdef存入,且权重为输入对象数组。
{
// 生成钱N个字符节点,输入权重和字符信息
node[i] = new HFMnode();
node[i]->weight = w[i];
node[i]->data = ch;
pri_queue.push(node[i]);
}
for (int i = N; i < 2*N-1; ++i)
{
// 后面新生成的N-1个节点
node[i] = new HFMnode();
if (pri_queue.top()->data != '/')
{
//队首节点不是新生成的,队首放右边
right = pri_queue.top();
right->code = '1';
pri_queue.pop();
left = pri_queue.top();
left->code = '0';
pri_queue.pop();
}
else
{
//队首节点是新生成的,队首放左边
left = pri_queue.top();
left->code = '0';
pri_queue.pop();
right = pri_queue.top();
right->code = '1';
pri_queue.pop();
}
// 新节点权值、上下连接指针对接
node[i]->weight = left->weight + right->weight;
node[i]->lp = left;
node[i]->rp = right;
left->parent = node[i];
right->parent = node[i];
pri_queue.push(node[i]); // 新生成的结点cherub队列
}
root = pri_queue.top(); // 最后还剩一个结点,是根节点
creatHuffCode();
for (int i = 0; i < 2*N-1; ++i)
{
delete node[i];
}
}
void creatHuffCode()
{
HFMnode* parent;
string huffCode; // 霍夫曼编码
int codelen = 0; // 输入的字符串编码后的总长度bits
for (int i = 0; i < N; ++i)
{
huffCode = "";
parent = node[i]; // 从自己(叶子节点)开始向上找父结点,直到root
cout << i + 1 << " " << node[i]->data << " The Huffman encoding is : ";
while(parent != root)
{
//huffCode.push_back(parent->code); // 将路径中的编码汇成字符串
huffCode+=parent->code;
parent = parent->parent;
}
reverse(huffCode.begin(), huffCode.end()); // 将最终的编码翻转一下
cout << huffCode << endl;
codelen += huffCode.size()*node[i]->weight; // 单字节code长*出现的次数
}
cout << "The Huffman encoding length of the string is " << codelen << " bits." << endl;
}
};
int main()
{
HuffmanTree huff;
cout << "Please enter the weight of the character , total " << N << " character: " << endl;
int w[] = new int[N];
for (int i = 0; i < N; ++i)
{
cout << "No. " << i+1 << " ";
cin >> w[i];
}
huff.creatTree_outputCode(w);
// system("pause");
return 0;
}
六、Prim和Kruskal最小生成树
Prim 最小生成树的代码链接(C++代码):
Kruskal最小生成树代码链接(C++代码):
七、Dijkstra单源最短路径
未完待续……
八、移除K个数,使得最终数字最小
abcdef.....
从高位a开始,与左边低一位的b数字进行比较,a > b,则移除a.。否则,继续用b 与左边低一位c进行比较。
4556847594546->remove 8 -> 455647594546 -> remove 6 -> 45547594546 -> remove second 5 -> 4547594546
-> remove 5-> 447594546......
九、排队的n个人,等待被服务,只有一个服务员。每个人服务时间不等,如何n个人总的等待时长最小。
由处理时间最短的开始服务。