编程小练习(1)

Game 24点游戏算法

问题:给4个1-10的数字,通过加减乘除,得到数字为24就算胜利。输入:4个1-10的数字;输出:True or False;

方法一 暴力搜索

#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
using namespace std;

void cal(double re[6], double a, double b) {
	re[0] = a + b;
	re[1] = a - b;
	re[2] = b - a;
	re[3] = a * b;
	re[4] = a * 1.0 / b;
	re[5] = b * 1.0 / a;
}

bool is24Points(double a, double b) {
	double re[6];
	cal(re, a, b);
	int i;
	for (i = 0; i < 6; ++i) {
		if (re[i] == 24) {
			return true;
		}
	}
	return false;
}

void calThree(double re[108], double a, double b, double c) {
	int i, j, k;
	k = 0;
	double fi[6];
	double tt[6];
	cal(fi, a, b);
	for (i = 0; i < 6; ++i) {
		cal(tt, fi[i], c);
		for (j = 0; j < 6; ++j) {
			re[k++] = tt[j];
		}
	}
	cal(fi, a, c);
	for (i = 0; i < 6; ++i) {
		cal(tt, fi[i], b);
		for (j = 0; j < 6; ++j) {
			re[k++] = tt[j];
		}
	}
	cal(fi, b, c);
	for (i = 0; i < 6; ++i) {
		cal(tt, fi[i], a);
		for (j = 0; j < 6; ++j) {
			re[k++] = tt[j];
		}
	}
}

bool Game24Points(int a, int b, int c, int d) {
	double re[108];
	int i;
	calThree(re, b, c, d);
	for (i = 0; i < 108; i++) {
		if (is24Points(re[i], a))
			return true;
	}
	calThree(re, a, c, d);
	for (i = 0; i < 108; i++) {
		if (is24Points(re[i], b))
			return true;
	}
	calThree(re, a, b, d);
	for (i = 0; i < 108; i++) {
		if (is24Points(re[i], c))
			return true;
	}
	calThree(re, a, b, c);
	for (i = 0; i < 108; i++) {
		if (is24Points(re[i], d))
			return true;
	}
	return false;
}

int main() {
	cout << Game24Points(1, 2, 3, 4) << endl;
	cout << Game24Points(7, 2, 1, 10) << endl;
	cout << Game24Points(7, 7, 7, 7) << endl;
	return 0;
}

方法二 递归回溯

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <cstdlib>
#include <iostream>
#include <math.h>

const double EPS = 1e-6;
double s[4] = { 0, 0, 0, 0 };

bool process(int n) {
	if (n == 1) {
		if (fabs(24 - s[0]) < EPS)
			return true;
		else
			return false;
	}
	double a, b;
	int i, j;
	for (i = 0; i < n; i++)
		for (j = i + 1; j < n; j++) {
			a = s[i];
			b = s[j];

			s[j] = s[n - 1];

			s[i] = a + b;
			if (process(n - 1))
				return true;
			s[i] = a - b;
			if (process(n - 1))
				return true;
			s[i] = b - a;
			if (process(n - 1))
				return true;
			s[i] = a * b;
			if (process(n - 1))
				return true;
			if (b != 0) {
				s[i] = a / b;
				if (process(n - 1))
					return true;
			}
			if (a != 0) {
				s[i] = b / a;
				if (process(n - 1))
					return true;
			}

			s[i] = a;
			s[j] = b;
		}
	return false;
}

bool Game24Points(int a, int b, int c, int d) {
	s[0] = a;
	s[1] = b;
	s[2] = c;
	s[3] = d;
	if (process(4))
		return true;
	else
		return false;

}

int main() {
	std::cout << Game24Points(1, 2, 3, 4) << "\n";
	std::cout << Game24Points(0, 0, 0, 1) << "\n";
	return 0;
}

周期串问题

问题:一个字符串可以由某个长度为k的字符串重复多次得到,称该串以k为周期。编写程序求周期,例如,abcabcabcabc以3为周期。

#include <iostream>

int GetMinPeriod(char *inputstring) {
    int i, j;
    int len = strlen(inputstring);
    int result = len;
    for (i = 1; i < len / 2 + 1; i++) {
        for (j = 0; j < len - i; j++) {
            if (inputstring[j] != inputstring[j + i])
                break;
        }
        if (j == len - i) {
            result = i;
            break;
        }
    }
    return result;
}

int main(){
    char* p = "abcabcabcabc";
    std::cout << GetMinPeriod(p); //3
    return 0;
}

删除重复字符

问题:给定一个字符串,将字符串中所有和前面重复多余的字符删除,其余字符保留,输出处理后的字符串。需保证字符顺序,并区分大小写。

#include <map>
#include <iostream>

int GetResult(const char *input, char *output)
{
	if (input == NULL || output == NULL)
		return -1;

	std::map<char, int> m;
	const char *p = input;

	while (*p) m[*p++] = 0;
	p = input;
	while (*p) {
		++m[*p];
		if (m[*p] == 1)	*output++ = *p;
		++p;
	}
	*output = '\0';
	return 0;
}

int main()
{
	char *p = "aabbcdae";
	char *ou = (char *) malloc(1000);
	GetResult(p, ou);
	std::cout << ou ;
}

N皇后

问题:国际象棋中任意两个皇后都不能处于同一行、同一列或同一斜线上。把N个皇后放在棋盘(N×N) 上,求放置N 皇后方案的个数。

#include <stdio.h>
#include <stdlib.h>
#include <iostream>

static int g_table[20] = {0};

bool find(int row, int col)
{
	for (int i = 1; i < row; ++i) {
		if (g_table[i] == col || abs(i - row) == abs(g_table[i] - col))
			return false;
	}

	return true;
}

void place(int row, int n, int *count)
{
	if (row > n) {
		++*count;
		return;
	}

	for (int col = 1; col <= n; col++) {
		if (find(row, col)) {
			g_table[row] = col;
			place(row + 1, n, count);
		}
	}
}

int PlaceQueenMethodNum(int n)
{
	int count = 0;
	place(1, n, &count);
	return count;
}

int main()
{
	std::cout << PlaceQueenMethodNum(8) << "\n";  // 92
	std::cout << PlaceQueenMethodNum(12) << "\n"; // 14200
}

大数阶乘

问题:请设计一个程序,使其可以计算100以内的数的阶乘,结果用字符串的形式输出。

#include <iostream>
using namespace std;
void CalcNN(int n, char *pOut) {
	int a[5000];
	memset(a, 0, sizeof(a));
	a[0] = 1;
	int i, j, k, len = 0;
	for (i = 1; i <= n; ++i) {
		for (j = 0; j <= len; ++j)
			a[j] *= i;
		for (j = 0; j <= len; ++j) {
			if (a[j] < 10)
				continue;
			k = j;
			while (k <= len) {
				if (a[len] > 9)
					++len;
				a[k + 1] += a[k] / 10;
				a[k] %= 10;
				++k;
			}
		}
	}
	char *p = pOut;
	for (i = len; i >= 0; --i) {
		*p++ = '0' + a[i];
	}
	*p = '\0';
	return;
}

int main() {
	char *p = (char *) malloc(1000);
	CalcNN(13, p);
	cout << p;
}

对象管理器

问题:实现一个对象管理器,可以插入,查找,删除。插入要求首先判断是否已经有相同对象存在,删除操作可以通过通配符进行批量删除;

#include <set>
#include <vector>
using std::set;
using std::vector;

class Myobj {
public:
    Myobj():key1(0),key2(0),key3(0) {}
    Myobj(unsigned int key1,unsigned int key2,unsigned int key3):
        key1(key1),key2(key2),key3(key3) {}
    bool operator < (const Myobj& a) const{
        if(key1 < a.key1)
            return true;
        if(key1 == a.key1 && key2 < a.key2)
            return true;
        if(key1 == a.key1 && key2 == a.key2 && key3 < a.key3)
            return true;
        return false;
    }
    bool operator == (const Myobj& a) const{
        if(key1 == a.key1 && key2 == a.key2 && key3 == a.key3){
            return true;
        } else {
            return false;
        }
    }

public:
    unsigned int key1;
    unsigned int key2;
    unsigned int key3;
};

static set<Myobj> g_myobj;

int AddObject (unsigned int key1, unsigned int key2, unsigned int key3) {
    Myobj o(key1,key2,key3);
    if(g_myobj.insert(o).second)
        return 0;
    else
        return -1;
}


void DeleteObject (unsigned int key1, unsigned int key2, unsigned int key3) {
    set<Myobj>::iterator it;
    vector< set<Myobj>::iterator > ve;
    for(it = g_myobj.begin(); it != g_myobj.end(); ++it){
        if( (key1 == 0xFFFFFFFF || key1 == it->key1) &&
            (key2 == 0xFFFFFFFF || key2 == it->key2) &&
            (key3 == 0xFFFFFFFF || key3 == it->key3) )
        ve.push_back(it);
    }
    for(int i = 0; i < ve.size(); ++i){
        g_myobj.erase(ve[i]);
    }
    return ;
}


int IsObjectExist (unsigned int key1, unsigned int key2, unsigned int key3) {
    Myobj o(key1,key2,key3);
    if(g_myobj.count(o))
        return 1;
    else
        return 0;
}

void Clear(void) {
    g_myobj.clear();
    return;
}


删除链表重复节点剩余逆序输出

问题:删除单链表中重复的节点,删除重复不是保留一个,而是都删除,剩余节点逆序输出,输出节点除了首节点外其它需自己重新开辟内存。

#include <stdlib.h>
#include <map>
#include <vector>
#include <algorithm>
#include "oj.h"
using std::map;
using std::vector;
using std::reverse;

int iChanProcess(strNode * pstrIn, strNode * pstrOut) {
	if (pstrIn == NULL || pstrOut == NULL)
		return 0;

	map<int, int> m;
	strNode *p = pstrIn, *temp = NULL;
	while (p != NULL) {
		m[p->data] = 0;
		p = p->pstrNext;
	}

	p = pstrIn;
	while (p != NULL) {
		m[p->data]++;
		p = p->pstrNext;
	}

	p = pstrIn;
	vector<strNode*> ve;
	while (p != NULL) {
		if (m[p->data] == 1) {
			temp = (strNode *) malloc(sizeof(strNode));
			temp->data = p->data;
			temp->pstrNext = NULL;
			ve.push_back(temp);
		}
		p = p->pstrNext;
	}

	reverse(ve.begin(), ve.end());
	for (unsigned int i = 0; i < ve.size() - 1; ++i) {
		ve[i]->pstrNext = ve[i + 1];
	}
	ve[ve.size() - 1] = NULL;

	pstrOut->data = ve[0]->data;
	pstrOut->pstrNext = ve[0]->pstrNext;
	free(ve[0]);
	return 0;
}

void vFreeChan(strNode * pstrChan) {
	strNode *p;
	while (pstrChan != NULL) {
		p = pstrChan;
		pstrChan = pstrChan->pstrNext;
		free(p);
	}
	return;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值