实验一

梵塔问题

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
ll ans = 0;
void dfs(char a, char b, char c, int n)
{
	if(n == 1)
	{
		ans++;
		cout << a << " -> " << c << "\n";
	}
	else
	{
		dfs(a, c, b, n - 1);
		ans++;
		cout << a << " -> " << c << "\n";
		dfs(b, a, c, n - 1);
	}
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int n;
	cin >> n;
	dfs('A', 'B', 'C', n);
	cout << ans << "\n";
	return 0;
}

传教士野人渡河问题

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
const int dx[] = {1, 0, 0, 2, 1};
const int dy[] = {1, 2, 1, 0, 0};

array<int, 3> ans[N], tot[N];
map<array<int, 3>, bool> v;
int sum, tt = -1;
int a, b;

// 本岸位置的 野人 和 传教士 数量  1 : 本岸   -1 :对岸 
bool check(array<int, 3> t)
{
	int y = t[0], c = t[1], f = t[2];
	if(y < 0 || c < 0 || y > a || c > b) return 0;
	if((c != 0 && y > c) || (b - c != 0 && a - y > b - c)) return 0;
	return 1;
}
void dfs(array<int, 3> t)
{
	int y = t[0], c = t[1], f = t[2];
	if(y == 0 && c == 0 && f == -1)
	{
		sum++;
		cout << sum << "\n";
		for(int i = 0; i <= tt; i++)
		{
			cout << (ans[i][2] == 1 ? "去" : "回") << " ";
			cout << "野人:" << ans[i][0] << " 传教士:" << ans[i][1] << "\n";
		}
		return;
	}
	array<int, 3> tmp;
	for(int i = 0; i < 5; i++)
	{
		tmp = {y - f * dx[i], c - f * dy[i], -f};
		if(check(tmp) && !v[tmp])
		{
			v[tmp] = 1;
			ans[++tt] = {dx[i], dy[i], f};
			dfs(tmp);
			v[tmp] = 0;
			--tt;
		}
	}
}
int main()
{
	cout << "请分别输入野人数量和传教士数量:";
	cin >> a >> b;
	array<int, 3> t = {a, b, 1};
	v[t] = 1;
	dfs(t);
	v[t] = 0;
	return 0;
}

实验二

宽度优先和深度优先求解路径

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5, M = 2 * N;
const int inf = 0x3f3f3f3f;

int n, m;
int s, d;
int dis[N], vis[N], pre[N];

int e[M], h[N], ne[M], w[M], idx;
void add(int a, int b, int c)
{
	e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}
void dfs(int u)
{
	vis[u] = 1;
	if(u == d) return;
	for(int i = h[u]; ~i; i = ne[i])
	{
		int to = e[i], val = w[i];
		if(!vis[to] || dis[u] + val < dis[to])
		{
			dis[to] = dis[u] + val;
			pre[to] = u;
			dfs(to);
		}
	}
}
// 只能求不带权图 
void bfs(int s)
{
	queue<int> q;
	vis[s] = 1;
	q.push(s);
	while(!q.empty())
	{
		int t = q.front();
		q.pop();
		if(t == d) return;
		for(int i = h[t]; ~i; i = ne[i])
		{
			int to = e[i];
			if(vis[to]) continue;
			vis[to] = 1;
			dis[to] = dis[t] + 1;
			pre[to] = t;
			q.push(to);
		}
	}
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	
	memset(h, -1, sizeof h);
	cin >> n >> m >> s >> d;
	for(int i = 1; i <= m; i++)
	{
		int a, b, c;
		cin >> a >> b >> c;
		add(a, b, c);
	}
	
	memset(dis, 0x3f, sizeof dis);
	memset(pre, -1, sizeof pre);
	dis[s] = 0;
//	dfs(s);
	bfs(s);
	vector<int> path;
	int t = d;
	path.push_back(t);
	while(pre[t] != -1)
	{
		path.push_back(pre[t]);
		t = pre[t];
	}
	reverse(path.begin(), path.end());
	cout << "最短的路径:\n";
	for(int i = 0; i < int(path.size() - 1); i++)
		cout << path[i] << " -> " << path[i + 1] << "\n";
	cout << "最短路径:" << dis[d] << "\n";
	return 0;
}

/* sample 1 
8 10 1 8
1 2 1
1 5 1
2 5 1
2 3 1
5 3 1
5 6 1
3 4 1
3 7 1
3 8 1
4 8 1
*/

八数码问题

下面代码实现了N数码问题,不仅仅局限于八数码,但是求解效率有限

#include<bits/stdc++.h>
using namespace std;
using pis = pair<int, string>;
const int N = 500 * 500 + 5;
const int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
int n;

template <typename T>
struct Fenwick
{
	vector<T> tr;
	const int n;
	Fenwick(int n): n(n), tr(n) {}
	void insert(int x, T d)
	{
		for(; x < n; x += x & (-x))
			tr[x] += d;
	}
	T sum(int x)
	{
		T res = 0;
		for(; x; x -= x & (-x))
			res += tr[x];
		return res;
	}
	T RangeSum(int l, int r)
	{
		return sum(r) - sum(l - 1);
	}
};

int f(string s)
{
	int cnt = 0;
	for(int i = 0; i < int(s.size()); i++)
		if(s[i] != '0')
		{
			int cur = s[i] - '1';
			cnt += abs(cur / n - i / n) + abs(cur % n - i % n);
		}
	return cnt;
}
void bfs(string start, string end)
{
	char op[] = "URDL";
	
	unordered_map<string, int> dis;
	unordered_map<string, pair<char, string>> pre;
	priority_queue<pis, vector<pis>, greater<pis>> q;
	
	q.push({f(start), start});
	dis[start] = 0;
	while(!q.empty())
	{
		auto t = q.top();
		q.pop();
		string st = t.second;
		
		if(st == end) break;
		
		int x, y;
		for(int i = 0; i < int(st.size()); i++)
			if(st[i] == '0')
			{
				x = i / n, y = i % n;
				break;
			}
		
		for(int i = 0; i < 4; i++)
		{
			int nx = x + dx[i], ny = y + dy[i];
			if(nx < 0 || nx >= n || ny < 0 || ny >= n) continue;
			string t = st;
			swap(t[x * n + y], t[nx * n + ny]);
			if(!dis.count(t) || dis[st] + 1 < dis[t])
			{
				dis[t] = dis[st] + 1;
				pre[t] = {op[i], st};
				q.push({dis[t] + f(t), t});
			}
		}
	}
	string move;
	vector<string> state;
	state.push_back(end);
	while(end != start)
	{
		move += pre[end].first;
		end = pre[end].second;
		state.push_back(end);
	}
	reverse(move.begin(), move.end());
	reverse(state.begin(), state.end());
	
	for(int i = 0; i < int(move.size()); i++)
	{
		int cur = 0;
		for(int j = 0; j < n; j++)
			for(int k = 0; k < n; k++)
				cout << (state[i][cur++] - '0') << " \n"[k == n - 1];
		
		cout << "-----------------\n操作:" << move[i] << "\n";
		if(i == int(move.size() - 1))
		{
			int nxt = i + 1;
			cur = 0;
			for(int j = 0; j < n; j++)
				for(int k = 0; k < n; k++)
					cout << (state[nxt][cur++] - '0') << " \n"[k == n - 1];
		}
	}
	
}
int main()
{
	cout << "输入数码阶数:\n"; 
	cin >> n;
	vector<int> a(n * n), b(a);
	int cur = 0;
	cout << "输入初始状态和最终状态:\n";
	for(int i = 1; i <= n * n; i++)
	{
		int x;
		cin >> x;
		a[cur++] = x;
	}
	cur = 0; 
	for(int i = 1; i <= n * n; i++)
	{
		int x;
		cin >> x;
		b[cur++] = x;
	}
	
	Fenwick<int> tra(n * n + 1), trb(n * n + 1);
	int s = 0, d = 0, last = 0, row = -1;
	
	for(int i = 0; i < n * n; i++)
	{
		if(a[i] == 0)
		{
			last ++;
			row = i / n;
			continue;
		}
		s += (i - last - tra.sum(a[i]));
		tra.insert(a[i], 1);
	}
	last = 0;
	for(int i = 0; i < n * n; i++)
	{
		if(b[i] == 0)
		{
			last ++;
			row -= i / n;
			continue;
		}
		d += (i - last - trb.sum(b[i]));
		trb.insert(b[i], 1);
	}
	cout << s << " " << d << "\n";
	if((n & 1 && s % 2 != d % 2) || (n % 2 == 0 && (s + row) % 2 != d % 2))
	{
		cout << "Can't arrive the state!\n";
		return 0;
	}
	string start, end;
	for(int i = 0; i < n * n; i++)
		start += (char)(a[i] + '0');
	for(int i = 0; i < n * n; i++)
		end += (char)(b[i] + '0');
	bfs(start, end);
	return 0;
}
/* sample
3
2 3 4 1 5 0 7 6 8
1 2 3 4 5 6 7 8 0

2
0 1 3 2
1 2 3 0

4
1 2 3 4 5 7 11 8 9 6 12 15 13 10 14 0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 0
*/

实验三

A*算法实现15数码问题

和上题代码相同

#include<bits/stdc++.h>
using namespace std;
using pis = pair<int, string>;
const int N = 500 * 500 + 5;
const int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
int n;

template <typename T>
struct Fenwick
{
	vector<T> tr;
	const int n;
	Fenwick(int n): n(n), tr(n) {}
	void insert(int x, T d)
	{
		for(; x < n; x += x & (-x))
			tr[x] += d;
	}
	T sum(int x)
	{
		T res = 0;
		for(; x; x -= x & (-x))
			res += tr[x];
		return res;
	}
	T RangeSum(int l, int r)
	{
		return sum(r) - sum(l - 1);
	}
};

int f(string s)
{
	int cnt = 0;
	for(int i = 0; i < int(s.size()); i++)
		if(s[i] != '0')
		{
			int cur = s[i] - '1';
			cnt += abs(cur / n - i / n) + abs(cur % n - i % n);
		}
	return cnt;
}
void bfs(string start, string end)
{
	char op[] = "URDL";
	
	unordered_map<string, int> dis;
	unordered_map<string, pair<char, string>> pre;
	priority_queue<pis, vector<pis>, greater<pis>> q;
	
	q.push({f(start), start});
	dis[start] = 0;
	while(!q.empty())
	{
		auto t = q.top();
		q.pop();
		string st = t.second;
		
		if(st == end) break;
		
		int x, y;
		for(int i = 0; i < int(st.size()); i++)
			if(st[i] == '0')
			{
				x = i / n, y = i % n;
				break;
			}
		
		for(int i = 0; i < 4; i++)
		{
			int nx = x + dx[i], ny = y + dy[i];
			if(nx < 0 || nx >= n || ny < 0 || ny >= n) continue;
			string t = st;
			swap(t[x * n + y], t[nx * n + ny]);
			if(!dis.count(t) || dis[st] + 1 < dis[t])
			{
				dis[t] = dis[st] + 1;
				pre[t] = {op[i], st};
				q.push({dis[t] + f(t), t});
			}
		}
	}
	string move;
	vector<string> state;
	state.push_back(end);
	while(end != start)
	{
		move += pre[end].first;
		end = pre[end].second;
		state.push_back(end);
	}
	reverse(move.begin(), move.end());
	reverse(state.begin(), state.end());
	
	for(int i = 0; i < int(move.size()); i++)
	{
		int cur = 0;
		for(int j = 0; j < n; j++)
			for(int k = 0; k < n; k++)
				cout << (state[i][cur++] - '0') << " \n"[k == n - 1];
		
		cout << "-----------------\n操作:" << move[i] << "\n";
		if(i == int(move.size() - 1))
		{
			int nxt = i + 1;
			cur = 0;
			for(int j = 0; j < n; j++)
				for(int k = 0; k < n; k++)
					cout << (state[nxt][cur++] - '0') << " \n"[k == n - 1];
		}
	}
	
}
int main()
{
	cout << "输入数码阶数:\n"; 
	cin >> n;
	vector<int> a(n * n), b(a);
	int cur = 0;
	cout << "输入初始状态和最终状态:\n";
	for(int i = 1; i <= n * n; i++)
	{
		int x;
		cin >> x;
		a[cur++] = x;
	}
	cur = 0; 
	for(int i = 1; i <= n * n; i++)
	{
		int x;
		cin >> x;
		b[cur++] = x;
	}
	
	Fenwick<int> tra(n * n + 1), trb(n * n + 1);
	int s = 0, d = 0, last = 0, row = -1;
	
	for(int i = 0; i < n * n; i++)
	{
		if(a[i] == 0)
		{
			last ++;
			row = i / n;
			continue;
		}
		s += (i - last - tra.sum(a[i]));
		tra.insert(a[i], 1);
	}
	last = 0;
	for(int i = 0; i < n * n; i++)
	{
		if(b[i] == 0)
		{
			last ++;
			row -= i / n;
			continue;
		}
		d += (i - last - trb.sum(b[i]));
		trb.insert(b[i], 1);
	}
	cout << s << " " << d << "\n";
	if((n & 1 && s % 2 != d % 2) || (n % 2 == 0 && (s + row) % 2 != d % 2))
	{
		cout << "Can't arrive the state!\n";
		return 0;
	}
	string start, end;
	for(int i = 0; i < n * n; i++)
		start += (char)(a[i] + '0');
	for(int i = 0; i < n * n; i++)
		end += (char)(b[i] + '0');
	bfs(start, end);
	return 0;
}
/* sample
4
11 9 4 15 1 3 0 12 7 5 8 6 13 2 10 14
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 0
*/

使用A*算法求解最短路径

自定义路线图,求解最短路径

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using pdd = pair<ld, ld>;
using arr = array<int, 3>;
using vi = vector<int>;
using vl = vector<ll>;
constexpr int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
constexpr int inf = 0x3f3f3f3f;
constexpr ll linf = 0x3f3f3f3f3f3f3f3f;
constexpr int N = 1e5 + 5, M = N;
constexpr int mod = 1e9 + 7;
constexpr ld eps = 1e-8;
template <class T> void Min(T &a, const T b) { if (a > b) a = b; }
template <class T> void Max(T &a, const T b) { if (a < b) a = b; }
template <class T> void Add(T &a, const T b) { a += b; if(a >= mod) a -= mod; }
template <class T> void Sub(T &a, const T b) { a -= b; if(a < 0) a += mod; }

struct Node
{
	int x, y, dis, f;
	bool operator < (const Node a) const
	{
		return dis + f > a.dis + a.f;
	}
};
void solve()
{
	int n, m;
	cin >> n >> m;
	int sx, sy, fx, fy;
	cin >> sx >> sy >> fx >> fy;

	vector<vi> g(n + 1, vi(m + 1));
	
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= m; j++)
			cin >> g[i][j];

	// 浼颁环鍑芥暟
	auto f = [&](int x, int y) -> int { return abs(x - fx) + abs(y - fy); };
	
	priority_queue<Node> q;
	vector<vi> vis(n + 1, vi(m + 1));
	vector<vector<pii>> pre(n + 1, vector<pii>(m + 1, {-1, -1}));

	q.push({sx, sy, 0, f(sx, sy)});
	vis[sx][sy] = 1;

	int ans = -1;
	while(!q.empty())
	{
		auto t = q.top();
		q.pop();

		int x = t.x, y = t.y, d = t.dis;

		if(x == fx && y == fy)
		{
			ans = d;
			break;
		}

		for(int i = 0; i < 4; i++)
		{
			int nx = x + dx[i], ny = y + dy[i];
			if(nx < 1 || nx > n || ny < 1 || ny > m) continue;
			if(g[nx][ny] || vis[nx][ny]) continue;

			vis[nx][ny] = 1;
			pre[nx][ny] = {x, y};
			q.push({nx, ny, d + 1, f(nx, ny)});
		}
	}

	if(ans == -1)
	{
		cout << "Can't reach!\n";
		return;
	}
	vector<pii> path;
	int tx = fx, ty = fy;
	while(pre[tx][ty] != make_pair(-1, -1))
	{
		path.emplace_back(tx, ty);
		auto t = pre[tx][ty];
		tx = t.first, ty = t.second;
	}
	path.emplace_back(sx, sy);

	cout << "The shorted distance: " << ans << "\n";

	reverse(path.begin(), path.end());
	for(int i = 0; i < int(path.size()); i++)
	{
		auto [x, y] = path[i];
		cout << "(" << x << "," << y << ")";

		if(i != int(path.size()) - 1) cout << "->";
		else cout << "\n";
	}
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);

	int t;
	t = 1;
	// cin >> t;
	while(t--)
		solve();
	return 0;
}
/*
6 6
1 1 6 6
0 0 0 0 0 0
0 1 1 0 0 0
0 1 0 0 0 0
0 0 0 0 1 0
0 1 1 0 1 0
0 0 0 0 0 0
*/

实验四

动物识别系统

在这里插入图片描述

下面的代码有些迷,大多数是抄的

#include<bits/stdc++.h>

using namespace std;
using ll = long long;
using pii = pair<int, int>;
using vi = vector<int>;
using db = double;

const int ans_l = 25;  //从第25个特征开始
const int ans_r = 31;    //到第31个特诊为目标结论
const int object_middle_begin = 21;     //中间结果起始位置 
const int feature_num = 31;      //31种特征
const int rule_num = 15;      //15条规则
const int rule_pre = 4;    //规则中每个结果最多有4个前提条件
 
string features[feature_num] = {
	"有毛发", "产奶", "有羽毛", "会飞", "会下蛋",
	"吃肉", "有犬齿", "有爪", "眼盯前方", "有蹄",
	"反刍", "黄褐色", "有斑点", "有黑色条纹", "长脖",
	"长腿","不会飞","会游泳","黑白二色","善飞",
	"哺乳类","鸟类","食肉类","蹄类","金钱豹",
	"虎","长颈鹿","斑马","鸵鸟","企鹅","信天翁"
};
 
int rule_prerequisite[rule_num][rule_pre] = {
	{1, 0, 0, 0},
	{2, 0, 0, 0},
	{3, 0, 0, 0},
	{4, 5, 0, 0},
	{21, 6, 0, 0},
	{7, 8, 9, 0},
	{21, 10, 0, 0},
	{21, 11, 0, 0},
	{23, 12, 13, 0},
	{23, 12, 14, 0},
	{24, 15, 16, 13},
	{24, 14, 0, 0},
	{22, 15, 16, 4},
	{22, 18, 19, 4},
	{22, 20, 0, 0}
};
 
int rule_result[rule_num] = {21, 21, 22, 22, 23, 23, 24, 24, 25, 26, 27, 28, 29, 30, 31 };
 
bool backward_reasoning(int num, vi message);
bool inference(int num, vi message)         //迭代推理机
{
	int ii, ij, ik, im, in;
	int hit_num = 0;          //输入前提也规则前提重合数
	int prerequisite_num;     //规则前提数
	vi message_c;           //迭代前提
	int num_c;                //迭代前提数量
	for (ik = 0; ik < num; ik++)     //剪枝函数
	{
		if (message[ik] >= ans_l && message[ik] <= ans_r)
		{
			cout << "归并信息:" << features[message[ik] - 1] << "\n";
			cout << "推理成功!" << "\n\n";
			exit(0);
		}
	}
	for (ii = 0; ii < rule_num; ii++)   //遍历规则匹配
	{
		prerequisite_num = 0;
		hit_num = 0;
		for (ij = 0; ij < rule_pre; ij++)   //计算规则集前提数
		{
			if (rule_prerequisite[ii][ij] == 0)
				break;
			prerequisite_num++;
		}
		for (ij = 0; ij < prerequisite_num; ij++)
		{
			for (ik = 0; ik < num; ik++)
			{
				if (rule_prerequisite[ii][ij] == message[ik])
					hit_num++;
			}
		}
		if (hit_num == prerequisite_num)  //满足某个规则集全部前提
		{
			bool flag;
			for (ik = 0; ik < num; ik++)
			{
				if (message[ik] == rule_result[ii])
					break;
			}
			if (ik == num)
			{
				num_c = num - hit_num+1;
				flag = true;
			}
			else
			{
				num_c = num - hit_num;
				flag = false;
			}
			message_c.resize(num_c);
			in = 0;
			for (ik = 0; ik < num; ik++)
			{
				for (im = 0; im < hit_num; im++)
				{
					if (rule_prerequisite[ii][im] == message[ik])
						break;
				}
				if (im < hit_num)
					continue;
				message_c[in++] = message[ik];
			}
			if (flag == true)
				message_c[in] = rule_result[ii];
			cout << "推导信息:";
			for (int iz = 0; iz < num; iz++)
				cout << features[message[iz]-1] << " ";
			cout << "\n";
			return inference(num_c, message_c);
		}
	}
	cout << "归并信息:";
	for (int iz = 0; iz < num; iz++)
		cout << features[message[iz]-1] << " ";
	cout << endl;
	backward_reasoning(num,message);
	return false;
}
 
bool backward_reasoning(int num, vi message)   //反向推理
{
	int ii,ij,ik;
	int prerequisite_num = 0;
	int hit_num = 0;
	vi need_rule_number(rule_num);
	vi hit_rule_number(rule_num);
	float hit_rule_rate[rule_num];
	float best_hit_rule_rate=0;
	int best_hit_rule_number;
	vi new_message;
	for (int i = 0; i < rule_num; i++)   //遍历规则匹配
	{
		prerequisite_num=0;
		hit_num=0;
		for (int j = 0; j < rule_pre; j++)   //计算规则集前提数
		{
			if (rule_prerequisite[i][j] == 0) break;
			prerequisite_num++;
		}
		need_rule_number[i] = prerequisite_num;
		for (int j = 0; j < prerequisite_num; j++)   //计算输入信息命中规则集中的前提数
		{
			for (int k = 0; k < num; k++)
			{
				if (rule_prerequisite[i][j] == message[k]) 
					hit_num++;
			}
		}
		hit_rule_number[i] = hit_num;
		hit_rule_rate[i] = (float)hit_num / prerequisite_num;  //命中率
		int j;
		for(j = 0; j < num; j++)
		{
			if(message[j] == rule_result[hit_rule_number[i]])
				break;
		}
		if(hit_rule_rate[i] == 1 && j == num)
		{
			new_message.resize(num + 1);
			for(int k = 0; k < num; k++)
				new_message[k] = message[k];
			new_message[num] = rule_result[hit_rule_number[i]];
			num++;
			return inference(num,new_message);
		}
		cout<<"rule "<<setw(2)<<i<<" -> "<<setw(8)<<features[rule_result[i]-1]
		<<"命中率:"<<hit_rule_rate[i]<<endl;
	}
	best_hit_rule_number=-1;
	for(int i = 0; i < rule_num; i++)
	{
		if(best_hit_rule_rate < hit_rule_rate[i] && rule_result[i] >= object_middle_begin)
		{
			best_hit_rule_rate = hit_rule_rate[i];
			best_hit_rule_number = i;
		}
	}
	if(best_hit_rule_number == -1)
	{
		cout << "您输入的信息对本系统无效!按任意键退出...\n\n";
		exit(0);
	}
	cout << "\n";
	cout << "best_hit_rule_number=" << best_hit_rule_number << "\n";
	cout << "best_hit_rule_rate=" << best_hit_rule_rate << "\n";
	cout << "最佳匹配最终结果=" << features[rule_result[best_hit_rule_number] - 1] << "\n";
	for(ii = 0; ii < need_rule_number[best_hit_rule_number]; ii++)
	{
		for(ij = 0; ij < num; ij++)
		{
			if(rule_prerequisite[best_hit_rule_number][ii] == message[ij])
				break;
		}
		if(ij != num) continue;
		else
		{
			if(rule_prerequisite[best_hit_rule_number][ii]<object_middle_begin)
			{
				cout<<endl<<"请问您持有的信息是否包含\"";
				cout<<features[rule_prerequisite[best_hit_rule_number][ii]-1];
				cout<<"\"?(y or n)"<<endl;
				char input;
				while(true)
				{
					cin>>input;
					if(input=='n')
					{
						new_message.resize(num);
						for(ik=0;ik<num;ik++)
							new_message[ik]=message[ik];
						break;
					}
					else if(input=='y')
					{
						new_message.resize(num + 1);
						for(ik=0;ik<num;ik++)
							new_message[ik]=message[ik];
						new_message[num]=rule_prerequisite[best_hit_rule_number][ii];
						num++;
						return inference(num,new_message);
					}
					else cout<<"请重新输入(y or n)!";
				}
			}
			else      //询问是否有中间结果rule_prerequisite[best_hit_rule_number][ii]
			{	
				int middle_result=rule_prerequisite[best_hit_rule_number][ii];
				for(ii=0;ii<rule_num;ii++)
				{
					if(rule_result[ii] == middle_result)
					{
						for(ik = 0; ik < need_rule_number[ii]; ik++)
						{
							if(rule_prerequisite[ii][ik] >= object_middle_begin-1)
								continue;
							for(ij = 0; ij < num; ij++)
							{
								if(rule_prerequisite[ii][ik] == message[ij])
									break;
							}
							if(ij != num) continue;
							else
							{
								cout << "\n请问您持有的信息是否包含\"";
								cout << features[rule_prerequisite[ii][ik]-1];
								cout << "\"?(y or n)\n";
								char input;
								while(true)
								{
									cin >> input;
									if(input == 'n') break;
									else if(input == 'y')
									{
										new_message.resize(num + 1);
										for(int q = 0; q < num; q++)
											new_message[q] = message[q];
										new_message[num] = rule_prerequisite[best_hit_rule_number][ii];
										num++;
										return inference(num, new_message);
									}
									else cout<<"请重新输入(y or n)!";
								}
							}
						}
					}
				}
			}
		}
	}
	return true;
}
 
int main()
{
	int num;
	for(int i = 0; i < feature_num; i++)
	{
		cout << setiosflags(ios::left);
		cout << setw(2) << i + 1 << ":" << setw(10) << features[i] << "  ";
		if(i % 4 == 3) cout << "\n";
	}
	cout << "\n\n" << "请输入初始特征个数:" << "\n";
	cin >> num;
	vector<int> message(num);
	cout << "请输入已有信息:" << "\n";
	for (int i = 0; i < num; i++)
		cin >> message[i];
	cout << endl << "初始信息:";
	for (int i = 0; i < num; i++)
		cout << features[message[i] - 1] << " ";
	cout << "\n\n";
	if(!inference(num, message))
		cout << "你的输入无法得出结果!" << "\n";
	return 0;
}

自行设计故障诊断系统

根据上面的代码改的,自己写的不太多

#include<bits/stdc++.h>

using namespace std;
using ll = long long;
using pii = pair<int, int>;
using vi = vector<int>;
using db = double;

const int ans_l = 17;  //从第25个特征开始
const int ans_r = 22;    //到第31个特征为目标结论
const int object_middle_begin = 15;     //中间结果起始位置 
const int feature_num = 22;      //22种特征
const int rule_num = 8;      //8条规则
const int rule_pre = 4;    //规则中每个结果最多有4个前提条件

/*
前提条件:14
屏幕亮, 屏幕不亮, 键盘指示灯亮, 键盘指示灯不亮, 鼠标指示灯亮, 鼠标指示灯不亮, 
电源指示灯亮, 电源指示灯不亮, 充电亮起, 键盘不响应, 鼠标不响应, 画面不响应,
画面花屏, 画面蓝屏 

中间结论:2
电源问题,  所有指示灯亮 

结论:6
电池没电, 鼠标故障, 键盘故障, 内存过小未响应, 系统程序故障, 显示器故障 

规则:
屏幕亮 && 键盘指示灯亮 && 鼠标指示灯亮 && 电源指示灯亮 -> 所有指示灯亮 
屏幕不亮 && 键盘指示灯不亮 && 鼠标指示灯不亮 && 电源指示灯不亮 -> 电源问题 
电源问题 && 充电亮起 -> 电池没电 
键盘指示灯亮 && 键盘不响应 -> 键盘故障
鼠标指示灯不亮 && 鼠标不响应 -> 鼠标故障
画面不响应 && 所有指示灯亮 -> 内存过小未响应
画面花屏 && 所有指示灯亮 -> 显示器故障 
所有指示灯亮 && 画面蓝屏 -> 系统程序故障 
*/ 

string features[feature_num] = {
"屏幕亮", "屏幕不亮", "键盘指示灯亮", "键盘指示灯不亮", "鼠标指示灯亮",
"鼠标指示灯不亮", "电源指示灯亮", "电源指示灯不亮", "充电亮起", "键盘不响应", 
"鼠标不响应", "画面不响应", "画面花屏", "画面蓝屏", "电源问题", 
"所有指示灯亮", "电池没电", "鼠标故障", "键盘故障", "内存过小未响应", 
"系统程序故障", "显示器故障" 
};
 
int rule_prerequisite[rule_num][rule_pre] = {
	{1, 3, 5, 7},
	{2, 4, 6, 8},
	{15, 9, 0, 0},
	{3, 10, 0, 0},
	{6, 11, 0, 0},
	{12, 16, 0, 0},
	{13, 16, 0, 0},
	{14, 16, 0, 0}
};
 
int rule_result[rule_num] = {16, 15, 17, 19, 18, 20, 22, 21};
 
bool backward_reasoning(int num, vi message);
bool inference(int num, vi message) 
{
	int ii, ij, ik, im, in;
	int hit_num = 0;          //输入前提也规则前提重合数
	int prerequisite_num;     //规则前提数
	vi message_c;           //迭代前提
	int num_c;                //迭代前提数量
	for (ik = 0; ik < num; ik++)     //剪枝函数
	{
		if (message[ik] >= ans_l && message[ik] <= ans_r)
		{
			cout << "归并信息:" << features[message[ik] - 1] << endl;
			cout << "推理成功!" << endl<<endl;
			exit(0);
		}
	}
	for (ii = 0; ii < rule_num; ii++)   //遍历规则匹配
	{
		prerequisite_num = 0;
		hit_num = 0;
		for (ij = 0; ij < rule_pre; ij++)   //计算规则集前提数
		{
			if (rule_prerequisite[ii][ij] == 0)
				break;
			prerequisite_num++;
		}
		for (ij = 0; ij < prerequisite_num; ij++)
		{
			for (ik = 0; ik < num; ik++)
			{
				if (rule_prerequisite[ii][ij] == message[ik])
					hit_num++;
			}
		}
		if (hit_num == prerequisite_num)  //满足某个规则集全部前提
		{
			bool flag;
			for (ik = 0; ik < num; ik++)
			{
				if (message[ik] == rule_result[ii])
					break;
			}
			if (ik == num)
			{
				num_c = num - hit_num+1;
				flag = true;
			}
			else
			{
				num_c = num - hit_num;
				flag = false;
			}
			message_c.resize(num_c);
			in = 0;
			for (ik = 0; ik < num; ik++)
			{
				for (im = 0; im < hit_num; im++)
				{
					if (rule_prerequisite[ii][im] == message[ik])
						break;
				}
				if (im < hit_num)
					continue;
				message_c[in++] = message[ik];
			}
			if (flag == true)
				message_c[in] = rule_result[ii];
			cout << "推导信息:";
			for (int iz = 0; iz < num; iz++)
				cout << features[message[iz]-1] << " ";
			cout << "\n";
			return inference(num_c, message_c);
		}
	}
	cout << "归并信息:";
	for (int iz = 0; iz < num; iz++)
		cout << features[message[iz]-1] << " ";
	cout << endl;
	backward_reasoning(num,message);
	return false;
}
 
bool backward_reasoning(int num, vi message)   //反向推理
{
	int ii,ij,ik;
	int prerequisite_num = 0;
	int hit_num = 0;
	vi need_rule_number(rule_num);
	vi hit_rule_number(rule_num);
	float hit_rule_rate[rule_num];
	float best_hit_rule_rate=0;
	int best_hit_rule_number;
	vi new_message;
	for (int i = 0; i < rule_num; i++)   //遍历规则匹配
	{
		prerequisite_num=0;
		hit_num=0;
		for (int j = 0; j < rule_pre; j++)   //计算规则集前提数
		{
			if (rule_prerequisite[i][j] == 0) break;
			prerequisite_num++;
		}
		need_rule_number[i] = prerequisite_num;
		for (int j = 0; j < prerequisite_num; j++)   //计算输入信息命中规则集中的前提数
		{
			for (int k = 0; k < num; k++)
			{
				if (rule_prerequisite[i][j] == message[k]) 
					hit_num++;
			}
		}
		hit_rule_number[i] = hit_num;
		hit_rule_rate[i] = (float)hit_num / prerequisite_num;  //命中率
		int j;
		for(j = 0; j < num; j++)
		{
			if(message[j] == rule_result[hit_rule_number[i]])
				break;
		}
		if(hit_rule_rate[i] == 1 && j == num)
		{
			new_message.resize(num + 1);
			for(int k = 0; k < num; k++)
				new_message[k] = message[k];
			new_message[num] = rule_result[hit_rule_number[i]];
			num++;
			return inference(num,new_message);
		}
		cout<<"rule "<<setw(2)<<i<<" -> "<<setw(8)<<features[rule_result[i]-1]
		<<"命中率:"<<hit_rule_rate[i]<<endl;
	}
	best_hit_rule_number=-1;
	for(int i = 0; i < rule_num; i++)
	{
		if(best_hit_rule_rate < hit_rule_rate[i] && rule_result[i] >= object_middle_begin)
		{
			best_hit_rule_rate = hit_rule_rate[i];
			best_hit_rule_number = i;
		}
	}
	if(best_hit_rule_number == -1)
	{
		cout << "您输入的信息对本系统无效!按任意键退出...\n\n";
		exit(0);
	}
	cout << "\n";
	cout << "best_hit_rule_number=" << best_hit_rule_number << "\n";
	cout << "best_hit_rule_rate=" << best_hit_rule_rate << "\n";
	cout << "最佳匹配最终结果=" << features[rule_result[best_hit_rule_number] - 1] << "\n";
	for(ii = 0; ii < need_rule_number[best_hit_rule_number]; ii++)
	{
		for(ij = 0; ij < num; ij++)
		{
			if(rule_prerequisite[best_hit_rule_number][ii] == message[ij])
				break;
		}
		if(ij != num) continue;
		else
		{
			if(rule_prerequisite[best_hit_rule_number][ii]<object_middle_begin)
			{
				cout<<endl<<"请问您持有的信息是否包含\"";
				cout<<features[rule_prerequisite[best_hit_rule_number][ii]-1];
				cout<<"\"?(y or n)"<<endl;
				char in;
				while(true)
				{
					cin >> in;
					if(in == 'n')
					{
						new_message.resize(num);
						for(ik = 0; ik < num; ik++)
							new_message[ik] = message[ik];
						break;
					}
					else if(in == 'y')
					{
						new_message.resize(num + 1);
						for(ik = 0; ik < num; ik++)
							new_message[ik] = message[ik];
						new_message[num] = rule_prerequisite[best_hit_rule_number][ii];
						num++;
						return inference(num, new_message);
					}
					else cout<<"请重新输入(y or n)!";
				}
			}
			else      //询问是否有中间结果rule_prerequisite[best_hit_rule_number][ii]
			{	
				int middle_result=rule_prerequisite[best_hit_rule_number][ii];
				for(ii=0;ii<rule_num;ii++)
				{
					if(rule_result[ii] == middle_result)
					{
						for(ik = 0; ik < need_rule_number[ii]; ik++)
						{
							if(rule_prerequisite[ii][ik] >= object_middle_begin-1)
								continue;
							for(ij = 0; ij < num; ij++)
							{
								if(rule_prerequisite[ii][ik] == message[ij])
									break;
							}
							if(ij != num) continue;
							else
							{
								cout << "\n请问您持有的信息是否包含\"";
								cout << features[rule_prerequisite[ii][ik]-1];
								cout << "\"?(y or n)\n";
								char input;
								while(true)
								{
									cin >> input;
									if(input == 'n') break;
									else if(input == 'y')
									{
										new_message.resize(num + 1);
										for(int q = 0; q < num; q++)
											new_message[q] = message[q];
										new_message[num] = rule_prerequisite[best_hit_rule_number][ii];
										num++;
										return inference(num, new_message);
									}
									else cout<<"请重新输入(y or n)!";
								}
							}
						}
					}
				}
			}
		}
	}
	return true;
}
 
int main()
{
	int num;
	for(int i = 0; i < feature_num; i++)
	{
		cout << setiosflags(ios::left);
		cout << setw(2) << i + 1 << ":" << setw(10) << features[i] << "  ";
		if(i % 4 == 3) cout << "\n";
	}
	cout << "\n\n" << "请输入初始特征个数:" << "\n";
	cin >> num;
	vector<int> message(num);
	cout << "请输入已有信息:" << "\n";
	for (int i = 0; i < num; i++)
		cin >> message[i];
	cout << endl << "初始信息:";
	for (int i = 0; i < num; i++)
		cout << features[message[i] - 1] << " ";
	cout << "\n\n";
	if(!inference(num, message))
		cout << "你的输入无法得出结果!" << "\n";
	return 0;
}

实验五

使用遗传算法求解函数最大值

在这里插入图片描述

#include<bits/stdc++.h>

using namespace std;
using ll = long long;
using arr = array<int, 20>;
using ld = long double;
using pdd = pair<ld, ld>;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
ll rnd(ll l, ll r) { return uniform_int_distribution<ll>(l, r)(rng); }

const int person_num = 500;
const ld vary_probability = 0.9;
const int epoch = 10;
const int length = 20;
const int iteration = 25;

vector<arr> init(int tot = 1000, int len = 20)
{
	vector<arr> persons;
	map<arr, bool> vis;
	
	while((int)persons.size() != tot)
	{
		arr person;
		for(int i = 0; i < 20; i++)
		{
			int bit = rnd(0, 1);
			person[i] = bit;
		}
		if(!vis[person])
		{
			persons.push_back(person);
			vis[person] = 1;
		}
	}

	return persons;
}

// 将20位的编码转换成x,y的十进制解
pdd decode(arr single)
{
	int x = 0, y = 0;
	for(int i = 0; i < 10; i++)
		x = x * 2 + single[i];
	for(int i = 10; i < 20; i++)
		y = y * 2 + single[i];
	
	return {10.0 * x / 1024, 10.0 * y / 1024};
}

// 计算x, y对应的函数值
ld calc(arr single)
{
	auto [x, y] = decode(single);
	ld up = 6.452 * (x + 0.125 * y) * 
		(cos(x) - cos(2 * y)) * (cos(x) - cos(2 * y));
	ld down = sqrt(0.8 + (x - 4.2) * (x - 4.2) + 2 * (y - 7) * (y - 7));

	ld ans = up / down + 3.226 * y;
	return ans;
}

int choose(vector<ld> val)
{
	ld temp = rnd(0, 1000000) / 1000000.0;

	vector<ld> val_psum;
	
	ld tot = 0;
	for(int i = 0; i < int(val.size()); i++)
		tot += val[i];

	ld s = 0;
	for(int i = 0; i < int(val.size()); i++)
	{
		s += val[i] / tot;
		val_psum.push_back(s);
	}

	int id = 0;
	while(temp > val_psum[id]) id++;

	return id;
}

arr cross(arr fa, arr mo)
{
	int cross_pos = rnd(0, 19);
	// unordered_map<int, int> vis;

	arr child;
	for(int i = 0; i < cross_pos; i++)
		child[i] = fa[i];
	for(int i = cross_pos; i < 20; i++)
		child[i] = mo[i];
	// vis[cross_pos] = 1;

	// while(calc(child) < 40.0)
	// {
	// 	// printf("Restart cross\n");
	// 	while(vis[cross_pos] && vis.size() < 20)
	// 		cross_pos = rnd(0, 19);
		
	// 	vis[cross_pos] = 1;
	// 	for(int i = 0; i < cross_pos; i++)
	// 		child[i] = fa[i];
	// 	for(int i = cross_pos; i < 20; i++)
	// 		child[i] = mo[i];

	// 	if((int)vis.size() >= 20)
	// 	{
	// 		child = fa;
	// 		break;
	// 	}
	// }
	return child;
}

arr vary(arr single)
{
	ld probability = (ld)rnd(0, 99) / 100.0;

	arr temp = single;
	if(probability < vary_probability)
	{
		int pos = rnd(0, 19);
		temp[pos] ^= 1;
		if(calc(temp) > calc(single))
			return temp;
	}
	return single;
}

int main()
{
	ld max_fval = 0;
	arr max_xy;

	for(int e = 1; e <= epoch; e++)
	{
		vector<arr> population = init(person_num, length);
		printf("----------------------The %d th epoch--------------------\n", e);
		for(int iter = 1; iter <= iteration; iter++)
		{
			printf("The %d th generation\n", iter);
			
			vector<arr> temp_population;

			vector<ld> val;
			for(int i = 0; i < int(population.size()); i++)
				val.push_back(calc(population[i]));
			
			int mx_id = max_element(val.begin(), val.end()) - val.begin();

			temp_population.push_back(population[mx_id]);

			for(int i = 1; i <= person_num; i++)
			{
				int fa_id = choose(val);
				int mo_id = choose(val);

				arr child = cross(population[fa_id], population[mo_id]);
				child = vary(child);

				temp_population.push_back(child);
			}
			population = temp_population;

			ld mx = 0;
			for(int i = 0; i < int(population.size()); i++)
			{
				ld tval = calc(population[i]);
				mx = max(mx, tval);
				if(tval > max_fval)
				{
					max_xy = population[i];
					max_fval = tval;
				}
			}
			printf("The %d th Max f(x, y): %.6Lf\n", iter, mx);
		}

	}
	pdd t = decode(max_xy);
	printf("x = %.6Lf , y = %.6Lf\n", t.first, t.second);
	printf("%.6Lf", max_fval);
	return 0;
}


使用遗传算法求解旅行商问题

在这里插入图片描述

我的图是二维的表格形式,故代码简化了一部分

/*
10
1 1
1 4
1 6
1 8
3 8
5 1
8 1
8 2
8 4
8 8
*/
#include<bits/stdc++.h>
#define x first
#define y second

using namespace std;
using pii = pair<int, int>;
using ld = long double;
using ll = long long;

const int epoch = 50;
const int person_num = 100;
const ld vary_probability = 0.3;
const int iteration = 20;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
ll rnd(ll l, ll r) { return uniform_int_distribution<ll>(l, r)(rng); }

vector<vector<ld>> d;

ld dis(pii a, pii b)
{
	return sqrt(1.0 * (a.x - b.x) * (a.x - b.x) + 
		1.0 * (a.y - b.y) * (a.y - b.y));
}

vector<vector<int>> init(int tot, int len)
{
	vector<vector<int>> persons;
	map<vector<int>, bool> vis;
	vector<int> person(len);

	iota(person.begin(), person.end(), 0);

	while(int(persons.size()) != tot)
	{
		// random_shuffle(person.begin(), person.end());
		shuffle(person.begin(), person.end(), rng);
		if(!vis[person])
		{
			persons.emplace_back(person);
			vis[person] = 1;
		}
	}
	return persons;
}


ld calc(vector<int> person)
{
	ld sum = 0;
	int n = person.size();
	for(int i = 0; i < n; i++)
	{
		int p = (i - 1 + n) % n;
		sum += d[person[p]][person[i]];
	}
	return sum;
}

int choose(vector<ld> val)
{
	ld temp = rnd(0, 100000) / 100000.0;

	vector<ld> val_psum;
	ld tot = 0;
	for(int i = 0; i < int(val.size()); i++)
	{
		val[i] = 1.0 / val[i];
		tot += val[i];
	}

	ld s = 0;
	for(int i = 0; i < int(val.size()); i++)
	{
		s += val[i] / tot;
		val_psum.emplace_back(s);
	}

	int id = 0;
	while(temp > val_psum[id] && id < int(val_psum.size())) id++;

	return id;
}

vector<int> cross(vector<int> fa, vector<int> mo)
{
	int l = rnd(0, int(fa.size()) - 1);
	int r = rnd(0, int(fa.size()) - 1);
	pii t = minmax(l, r);
	l = t.x, r = t.y;
// 3 5 6 [7 1 2] 4 0
// 3 1 0 [5 4 7] 6 2

	vector<int> conflict, p1(fa.size(), -1), p2(p1), child(fa.size());
	vector<bool> vis1(fa.size()), vis2(vis1);
	for(int i = 0; i < int(fa.size()); i++)
	{
		child[i] = fa[i];
		p1[fa[i]] = i;
	}

	for(int i = l; i <= r; i++)
		vis1[fa[i]] = vis2[mo[i]] = 1;
	
	for(int i = l; i <= r; i++)
	{
		child[i] = mo[i];
		p2[mo[i]] = i;
		if(!vis1[mo[i]])
			conflict.emplace_back(mo[i]);
	}

	for(int i = 0; i < int(conflict.size()); i++)
	{
		int id = p1[conflict[i]];
		while(vis2[child[id]])
			child[id] = fa[p2[child[id]]];
	}

	// for(int i = 0; i < int(child.size()); i++)
	// 	cout << child[i] << " \n"[i == int(child.size()) - 1];

	return child;
}

vector<int> mutation(vector<int> person)
{
	ld prob = (ld)rnd(0, 99) / 100.0;

	vector<int> temp = person;
	if(prob < vary_probability)
	{
		int l = rnd(0, person.size() - 1), r = rnd(0, person.size() - 1);
		if(l != r) swap(temp[l], temp[r]);
		if(calc(temp) > calc(person))
			return temp;
	}
	return person;
}

int main()
{
//	freopen("1.txt", "r", stdin);
	// printf("Please output the number of cities:");	
	
	int n;
	scanf("%d", &n);
	vector<int> path;
	ld min_path = 1e9;
	
	vector<pii> cities(n);
	for(int i = 0; i < n; i++)
		scanf("%d%d", &cities[i].x, &cities[i].y);

	d.resize(n, vector<ld>(n));
	for(int i = 0; i < n; i++)
		for(int j = i; j < n; j++)
			d[i][j] = d[j][i] = dis(cities[i], cities[j]);

	for(int e = 1; e <= epoch; e++)
	{
		vector<vector<int>> population = init(person_num, n);

		for(int iter = 1; iter <= iteration; iter++)
		{
			// printf("The %d th generation\n", iter);
			vector<vector<int>> temp_population;

			vector<ld> val(population.size());
			for(int i = 0; i < int(population.size()); i++)
				val[i] = calc(population[i]);

			int mn_id = min_element(val.begin(), val.end()) - val.begin();

			// 上一代最优种群保留到下一代
			temp_population.emplace_back(population[mn_id]);
			vector<int> child; 
			for(int i = 1; i < person_num; i++)
			{
				int fa_id = choose(val);
				int mo_id = choose(val);
				while(fa_id == mo_id)
					mo_id = choose(val);
				child = cross(population[fa_id], population[mo_id]);
				assert(child.size() > 0);
				child = mutation(child);

				temp_population.emplace_back(child);
			}
			population = temp_population;

			ld mn = 1e9;
			for(int i = 0; i < int(population.size()); i++)
			{
				ld tval = calc(population[i]);
				mn = min(mn, tval);
				if(tval < min_path)
				{
					path = population[i];
					min_path = tval;
				}
			}
			// printf("The %d th min path distance: %.6Lf\n", iter, mn);
		}
		printf("The %d th epoch min distance: %.6Lf\n", e, min_path);
	}
	printf("The path is:\n");
	for(int i = 0; i < int(path.size()); i++)
		cout << path[i] << " \n"[i == int(path.size()) - 1];

	printf("The min distance: %.6Lf\n", min_path);

	return 0;
}

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐