目录
1. 鸡兔同笼问题
类型:约束条件比经典鸡兔同笼问题宽松,无头的个数约束,直接模拟法。
描述
【问题】笼子里有若干只鸡和兔子,鸡有两只脚、兔子有四只脚,没有例外情况。已知笼子里脚的个数,问笼子里至多有多少只动物?至少有多少只动物?
【想法】对于同样数目的动物,鸡脚的总数肯定比兔子脚的总数要少,因此在计算笼子里至多有多少只动物时,应该把脚都算作鸡脚,在计算笼子里至少有多少只动物时,应该尽可能把脚都算作兔子脚。
输入
脚的个数(大于0的整数)
输出
至多有多少只动物,至少有多少只动物,其中兔子多少只。(输出中标点符号为中文,无需加换行符)
示例
(点击编辑器左上角{;}按钮编辑代码框)
输入
-111
输出
不合常理
输入
333
输出
不合常理
输入
6
输出
至多有3只动物,至少有2只动物,其中1只是兔子。
#include <iostream>
using namespace std;
int main()
{
int feets, maxNum, minNum,rabbits;
cin>>feets;//把其余代码写在下面:
if(feets <= 0 || feets % 2 != 0) {
cout << "不合常理";
}else{
maxNum = feets / 2;
minNum = feets / 4;
cout << "至多有"<<maxNum<<"只动物,至少有"<<minNum<<"只动物,其中兔子"<<minNum<<"只。";
}
return 0;
}
2. 猴子吃桃问题
类型:递推法之逆推
描述
一只猴子摘了很多桃子,每天吃现有桃子的一半多一个,到第n天时只有一个桃子,问原有桃子多少个?
输入
一个非负整数。
输出
一个非负整数。不加换行符。
示例
(点击编辑器左上角{;}按钮编辑代码框)
输入
5
输出
46
#include <iostream>
using namespace std;
int MonkeyPeach(int n)
{
int i, num = 1;
for(i=n-1;i>=1;i--)
num=(num+1)*2
return num;
}
int main()
{ int n;
cin>>n;
cout << MonkeyPeach(n);
return 0;
}
3. 代码填空
描述
给定一个包含正整数的 m×n 网格,(为降低难度m=5,n=3,存储在数组dist[5][3]中。)每次只能向下或者向右移动一步,定义路径长度是路径上经过的整数之和。请找出一条从左上角(位置为(0,0))到位置(k,l)的路径,使得路径长度最大。(注意,是求最长路径!!!)
输入
空格分隔的两个非负整数,表示目的方格的行标k和列标l。例如 4 2
输出
从左上角(位置(0,0))到位置(k,l)的最长路径的长度。例如396
#include <iostream>
using namespace std;
int main()
{
int m=5,n=3;
int a[5][3]={ 8,75,92, 6,65,71, 5,63,7, 5,87,90, 76,7,8 };
int dist[m][n], path[m][n], i, j,k,l;
cin>>k>>l;
dist[0][0] = a[0][0];
path[0][0] = 0;
for (j = 1; j <m ; j++) //填写第0行
{
dist[0][j] = dist[0][j-1] + a[0][j];
path[0][j] = 1;
}
for (i = 1; i <n; i++) //填写第0列
{
dist[i][0] = dist[i-1][0] + a[i][0];
path[i][0] = 0;
}
for (i = 1; i < m; i++) //填写每一行
for (j = 1; j <n; j++)
if (dist[i-1][j] > dist[i][j-1])
{
##### dist[i][j] = dist[i-1][j] + a[i][j];
path[i][j] = 0;
}
else
{
##### dist[i][j] = dist[i][j-1] + a[i][j];
path[i][j] = 1;
}
cout<<dist[k][l];//返回最优值
return 0;
}
4. 折半查找
描述
使用减治法进行折半查找
#include
using namespace std;
int BinSearch(int r[ ], int n, int k);
int main( )
{
int i, index, n = 9, k, r[n] = {2, 3, 5, 6, 8, 10, 15, 18, 20};
for (i = 0; i < n; i++)
cout< cout< cout<<"请输入待查值:";
cin>>k;
index = BinSearch(r, n, k);
if (index == 0) cout<<"查找失败"< else cout<<"查找成功,序号是:"< return 0;
}
int BinSearch(int r[ ], int n, int k)
{
int mid, low = 0, high = n - 1;
while (low <= high) //当查找区间存在
{
mid = (low + high) / 2;
if (k < r[mid]) ### high = mid - 1;
else if (k > r[mid]) ### low = mid + 1;
else return mid + 1; //查找成功,返回元素序号
}
return 0; //查找失败,返回0
}
5. 插入排序
描述
使用减治法进行插入排序
#include
using namespace std;
void InsertSort(int r[ ], int n);
int main( )
{
int i, n = 10, r[n] = {0, 3, 18, 5, 8, 6, 10, 2, 15, 20};
for (i = 1; i < n; i++)
cout< cout< InsertSort(r, n);
for (i = 1; i < n; i++)
cout< cout< return 0;
}
void InsertSort(int r[ ], int n)
{
int i, j;
for (i = 2; i <= n; i++) //从第2个记录开始执行插入操作
{
###### r[0] = r[i]; //暂存待插记录,设置哨兵
for (j = i - 1; r[0] < r[j]; j--) //寻找插入位置
##### r[j+1] = r[j]; //记录后移
r[j+1] = r[0];
}
}
6. 图着色问题
描述
使用贪心法解决图着色问题
#include
using namespace std;
int ColorGraph(int arc[100][100] , int n, int color[ ]);
int main( )
{
int arc[100][100] = {{0,1,0,0,0},{1,0,1,1,0},{0,1,0,0,1},{0,1,0,0,1},{0,0,1,1,0}};
int i, n = 5, color[n];
cout<<"需要颜色数为:"< cout<<"着色情况为:";
for (i = 0; i < n; i++)
cout< cout< return 0;
}
int ColorGraph(int arc[100][100] , int n, int color[ ])
{
int i, j, k = 0, flag = 1;
while (flag == 1)
{
k++; flag = 0; //取下一种颜色
for (i = 0; i < n; i++)
{
if (color[i] != 0) continue; //顶点i已着色
##### color[i] = k; //顶点i着颜色k
for (j = 0; j < n; j++)
if (arc[i][j] == 1 && color[i] == color[j]) break;
if (j < n) //发生冲突,取消涂色
{
##### color[i] = 0;
flag = 1;
}
}
}
return k;
}
7. 使用分治法进行归并排序
#include
using namespace std;
void Merge(int r[ ], int s, int m, int t);
void MergeSort(int r[ ], int s, int t);
int main( )
{
int i, n = 8, r[8] = {8,3,2,6,7,1,5,4};
MergeSort(r, 0, n-1);
for (i = 0; i < n; i++)
cout< return 0;
}
void Merge(int r[ ], int s, int m, int t)
{
int r1[t];
int i = s, j = m + 1, k = s;
while (i <= m && j <= t)
{
if (r[i] <= r[j]) r1[k++] = r[i++]; //较小者放入r1[k]
else r1[k++] = r[j++];
}
while (i <= m) //处理第一个子序列剩余记录
##### r1[k++] = r[i++];
while (j <= t) //处理第二个子序列剩余记录
##### r1[k++] = r[j++];
for (i = s; i <= t; i++) //将合并结果传回数组r
r[i] = r1[i];
}
void MergeSort(int r[ ], int s, int t) //对序列r[s]~r[t]进行归并排序
{
if (s == t) return; //只有一个记录,已经有序
else
{
int m = (s + t)/2; //划分
MergeSort(r, s, m); //归并排序前半个子序列
MergeSort(r, m+1, t); //归并排序后半个子序列
Merge(r, s, m, t); //合并两个有序子序列
}
}
8. 使用减治法进行堆排序
#include
using namespace std;
void SiftHeap(int r[ ], int k, int n);
void HeapSort(int r[ ], int n);
int main( )
{
int i, n = 9, r[n] = {3, 18, 5, 8, 6, 10, 2, 15, 20};
for (i = 0; i < n; i++)
cout< cout< HeapSort(r, n);
for (i = 0; i < n; i++)
cout< cout< return 0;
}
void SiftHeap(int r[ ], int k, int n)
{
int i, j, temp;
i = k; j = 2 * i + 1;
while (j < n) //筛选还没有进行到叶子
{
if (j < n-1 && r[j] < r[j+1]) j++; //比较i的左右孩子,j为较大者
if (r[i] > r[j]) //根结点已经大于左右孩子中的较大者
break;
else
{
temp = r[i]; ##### r[i] = r[j]; ##### r[j] = temp; //将被筛结点与结点j交换
i = j; j = 2 * i + 1; //被筛结点位于原来结点j的位置
}
}
}
void HeapSort(int r[ ], int n)
{
int i, temp;
for (i = (n-1)/2; i >= 0; i--) //初始建堆,最后一个分支的下标是(n-1)/2
SiftHeap(r, i, n) ;
for (i = 1; i <= n-1; i++) //重复执行移走堆顶及重建堆的操作
{
temp = r[0]; r[0] = r[n-i]; r[n-i] = temp;
SiftHeap(r, 0, n-i); //只需调整根结点
}
}
9. 程序改错(被注释掉的程序语句有错误)
描述
假设有面值为5元、2元、1元、5角、2角、1角的货币,需要找给顾客n角现金,付款问题要求找到一个付款方案,本题要求:贪心法求启发解,付出的货币张数为多少?
输入
一个非负整数,应找金额,单位为角。例如:100
输出
一个非负整数(货币张数)。例如:2
#include <iostream>
using namespace std;
int main()
{
int money[6] = {50, 20, 10, 5, 2, 1}, i, cnt = 0, n;
cin>>n;
for (i = 0; i < 6; i++) /*选取面值依次试探*/
{
//if (n <= money[i]) #### if (n >= money[i])
{
// cnt+=n%money[i]; #### cnt+=n/money[i];
// n = n/money[i]; #### n = n % money[i];
// if(n)break; #### if(!n)break;
}
}
//cout >> cnt; #### cout << cnt;
return 0;
}