1、QY等人,平时写代码的时候,喜欢吃一种叫“小鱼”的零食,用来提神醒脑(其实没有任何效果,我反而感觉他们越变越笨了)。突然小鱼的厂家做促销。凭3条小鱼尾巴,可以再换一条小鱼。而且可以一直循环下去,QY开心极了,于是拿出整个月的生活费买了N条小鱼。不过因为小鱼非常辣,所以QY每天也只能吃2条,他等某天吃光了,才会在第二天拿着鱼尾巴去换小鱼,然后继续吃。请你计算一下,最后他一共能吃多少天的小鱼呢?输入数据有多组,每组一行,仅包含一个数字N,即QY一开始买入的小鱼的数量。对应每组数据,输出QY能吃多少天,每个结果输出在一行中。
【输入样式】
1
2
3
4
5
【输出样式】
1
1
3
3
5
#include <stdio.h>
/*dayCount函数,计算n条鱼能吃几天,n为鱼的数量,surplus为剩余鱼尾数量*/
int dayCount(int n, int surplus){
int tail = n + surplus; //鱼尾数
if(tail == 0) return 0;
if(tail < 3) return 1;
return (n+1) / 2 + dayCount(tail / 3, tail % 3);
}
int main(){
int n; //n代表鱼数
while(scanf("%d", &n) != EOF){ //当输入文件结束符时退出循环
printf("%d\n", dayCount(n, 0));
}
return 0;
}
2、简单的背包问题,设有一个背包,可以放入的重量为m。现在有n件物品,质量都为正整数,从n件物品中挑选若干件,使得放入背包重量之和正好为m。找到一组解即可。输入的第一行为物品的总件数和背包的载重量,第二行为各物品的质量。输出放入背包中物品的序号和重量,每行输入一件。
【输入样式】
5 10
1 2 3 4 5
【输出样式】
5 5
4 4
1 1
#include <stdio.h>
#define M 100 //常量,代表最大物品数
int quality[M] = {0}; //存放各物品重量
int backpack[M] = {0}; //记录放入背包物品的序号
/*pack函数,i代表已放入背包物品的数量-1, n为当前物品的序号, m代表背包剩余可放质量*/
int pack(int i, int n, int m){
int judge = 0; //judge代表是否找到正确结果
if(n <= 0) return 0;
if(quality[n-1] == m){ //如果当前物品正好填满背包剩余空间,则返回1
backpack[i] = n;
return 1;
}
else if(quality[n-1] < m){ //如果当前物品质量小于背包剩余空间,则将物品放入后继续判断下一个物品
backpack[i] = n;
judge = pack(i+1, n-1, m-quality[n-1]);
}
if(!judge) return pack(i, n-1, m); //如果当前物品质量小于背包剩余空间,则直接判断下一个物品
return 1;
}
int main(){
int n, m, j; //n为物品总件数,m为背包载重量,j为循环变量
scanf("%d%d", &n, &m);
for(j = 0; j < n; j++){
scanf("%d", &quality[j]);
}
if(pack(0, n, m)){
j = 0;
while(backpack[j]){
printf("%d %d\n", backpack[j], quality[backpack[j]-1]);
j++;
}
}
return 0;
}
3、任何一个正整数都可以用2的幂次方表示:
如137=2^7+2^3+2^0,同时约定用括号来表示次方,即a^b可表示为a(b),所以137可表示为2(7)+2(3)+2(0),进一步可表示为:7=2^2+2+2^0,3=2+2^0,所以137可表示为2(2(2)+2+2(0))+2(2+2(0))+2(0))。
【输入样式】
1315
【输出样式】
2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)
#include <stdio.h>
/*函数功能:将n用2的幂次方表示*/
void powerOfTwo(int n, int m){
if(n == 1){
//程序出口
switch(m){
case 0: printf("2(0)"); break;
case 1: printf("2"); break;
case 2: printf("2(2)"); break;
default:printf("2("); powerOfTwo(m, 0); printf(")");//如果幂次大于二,将幂用2的幂次方表示
}
}
else
{
powerOfTwo(n / 2, m + 1);
if(n % 2) {
switch(m){
case 0: printf("+2(0)"); break;
case 1: printf("+2"); break;
case 2: printf("+2(2)"); break;
default:printf("+2("); powerOfTwo(m, 0); printf(")");
}
}
}
}
int main(){
int n;
scanf("%d", &n);
powerOfTwo(n, 0);
printf("\n");
return 0;
}
4、从楼上走到楼下共有h个台阶,每一步有三种走法:
(1)走一个台阶;(2)走两个台阶;(3)走三个台阶。列举出所有可能方案。
【输入样式】
4
【输出样式】
1111
112
121
13
211
22
31
/*台阶问题*/
#include <stdio.h>
void step(int state[], int i, int h){ //当前走到第i+1步,剩余h级台阶
int j, k;
for(j = 1; j <= 3; j++){ //当前步走j个台阶
state[i] = j;
if(h == j){ //走完一遍即输出
for(k = 0; k <= i; k++){
printf("%d", state[k]);
}
printf("\n");
}
else if(h > j) step(state, i+1, h-j); //台阶还有剩余,继续走下一步
state[i] = 0;
}
}
int main(){
int h; //台阶数
int state[100] = {0}; //存放第i+1步走的台阶数
scanf("%d", &h);
step(state, 0, h);
return 0;
}
5、在8*8的棋盘上,放置8个皇后(棋子),是两两之间互不攻击。所谓互不攻击是说任何两个皇后都要满足:
(1)不在棋盘的同一行;
(2)不在棋盘的同一列;
(3)不在棋盘的同一对角线上。
【输出格式】
15863724
16837425
17468253
17582463
24683175
……
(注:共有92组解,这里不一一列举。)
/*八皇后问题*/
#include <stdio.h>
int array[9] = {0}; //存放每个皇后所在列
int state[9] = {0}; //标记该列是否安全
int down[14] = {0}; //标记该右对角线是否安全
int up[14] = {0}; //标记该左对角线是否安全
void queen(int row){ //为第row个皇后安排位置
int col, i;
for(col = 1; col <= 8; col++){ //尝试将每个col安排给当前皇后
if(up[row+col-2] != 0 || down[col-row+7] != 0 || state[col] != 0) continue; //发生冲突,尝试下一个col
array[row] = col;
state[col] = 1;
up[row+col-2] = 1;
down[col-row+7] = 1;
if(row == 8) {
for(i = 1; i <= 8; i++){
printf("%d", array[i]);
}
printf("\n");
}
else queen(row + 1);
//回溯,恢复分配前状态
state[col] = 0;
array[row] = 0;
up[row+col-2] = 0;
down[col-row+7] = 0;
}
}
int main(){
queen(1);
return 0;
}
6、数的全排列问题,将n个数字1,2,3,…,n的所有排列按字典顺序枚举出来。
【输入格式】
3
【输出格式】
123
132
213
231
312
321
/*全排列问题*/
#include <stdio.h>
void arrange(int state[][10], int i, int n){ //为第i个盒子放小球
int j, k;
for(j = 1; j <= n; j++){ //将第j个小球放入第i个盒子
if(state[1][j] != 0) continue;
state[0][i] = j;
state[1][j] = 1;
if(i == n){
for(k = 1; k <= n; k++){
printf("%d", state[0][k]);
}
printf("\n");
}
else arrange(state, i+1, n);
//回溯,将第i个盒子置空,第j个小球恢复原始状态
state[0][i] = 0;
state[1][j] = 0;
}
}
int main(){
int n;
int state[2][10] = {0}; //第一行保存第i个盒子放的数,第二行标记第j个小球当前状态
scanf("%d", &n);
arrange(state, 1, n);
return 0;
}
7、数的组合问题。从1,2,…,n中取出m个数,将所有组合按照字典顺序列出。
【输入格式】
3 2
【输出格式】
12
13
23
/*数的组合问题*/
#include <stdio.h>
/*将第j个小球放入第i个盒子*/
void combine(int *com, int i, int j, int n, int m){
int k;
for(; j <= n; j++){
com[i] = j;
if(i+1 == m){
for(k = 0; k < m; k++){
printf("%d", com[k]);
}
printf("\n");
}
else combine(com, i+1, j+1, n, m);
com[i] = 0;
}
}
int main(){
int n, m;
int com[100] = {0};
scanf("%d%d", &n, &m);
combine(com, 0, 1, n, m);
return 0;
}
8、G将军有一支训练有素的军队,这个军队除开G将军外,每名士兵都有一个直接上级(可能是其他士兵,也可能是G将军)。现在G将军将接受一个特别的任务,需要派遣一部分士兵(至少一个)组成一个敢死队,为了增加敢死队队员的独立性,要求如果一名士兵在敢死队中,他的直接上级不能在敢死队中。G将军有多少种派出敢死队的方法。注意,G将军也可以作为一个士兵进入敢死队。输入的第一行包含一个整数n,表示包括G将军在内的军队的人数。军队的士兵从1至n编号,G将军编号为1。接下来n-1个数,分别表示编号为2, 3, …, n的士兵的直接上级编号,编号i的士兵的直接上级的编号小于i。输出一个整数,表示派出敢死队的方案数。由于数目可能很大,你只需要输出这个数除10007的余数即可。
【输入格式】
3
1 1
【输出格式】
4
样例说明
这四种方式分别是:
1. 选1;
2. 选2;
3. 选3;
4. 选2, 3。
数据规模与约定
对于20%的数据,n ≤ 20;
对于40%的数据,n ≤ 100;
对于100%的数据,1 ≤ n ≤ 100000。
/*这里采用了链栈存储,读者可更改为顺序栈存储*/
//LinkStack.h
struct Node{
int data;
Node *next;
};
class LinkStack
{
public:
LinkStack()
{top = NULL;}
~LinkStack();
void push(int x);
int pop();
bool isExist(int m);
void printStack();
private:
Node *top;
};
//LinkStack.cpp
#include <iostream>
#include "LinkStack.h"
using namespace std;
/*析构函数*/
LinkStack::~LinkStack()
{
Node *p;
while(top){
p = top;
top = top->next;
delete p;
}
}
/*压栈*/
void LinkStack::push(int x)
{
Node *p;
p = new Node;
p->data = x;
p->next = top;
top = p;
}
/*弹栈*/
int LinkStack::pop()
{
int data;
Node *p;
if(!top) cout << "下溢";
p = top;
top = p->next;
data = p->data;
delete p;
return data;
}
/*判断栈中是否存在元素m*/
bool LinkStack::isExist(int m){
Node *p = top;
while(p){
if(p->data == m) return true;
p = p->next;
}
return false;
}
/*遍历栈中元素,用于编程时对程序的检验*/
void LinkStack::printStack()
{
Node *p;
p = top;
while(p)
{
cout << p->data;
p = p->next;
}
cout << endl;
}
//Squad.cpp
#include <iostream>
#include "LinkStack.h"
using namespace std;
const int M = 100001; //树的最大结点数
/*count函数:返回值为空,tree指针指向树结构,stack引用链栈结构,m表示当前处理的士兵,n代表最后一个士兵
功能:计算编号在m到n可派出敢死队的方案数。
*/
void count(int *tree, LinkStack &stack, int m, int n){
for(; m <= n; m++){
if(stack.isExist(tree[m])) continue;
stack.push(m); //将可派出的士兵进栈
tree[0] = (tree[0]+1) % 10007; //每进栈一次,代表生成一种新的方案
count(tree, stack, m+1, n); //计算m+1到n可派出敢死队的方案数
stack.pop(); //回溯,即出栈
}
}
int main(){
int tree[M] = {0}; //用顺序表存储树,数据域存放其双亲结点,下标代表士兵编号
int n; //士兵的数量
LinkStack stack; //用链栈存放当前选中的士兵
cin >> n;
for(int i = 2; i <= n; i++){
cin >> tree[i];
}
count(tree, stack, 1, n); //计算编号在m到n可派出敢死队的方案数
cout << tree[0] << endl; //树的0号元素存储可生成的方案数
return 0;
}