<OJ_Sicily>Order Crossover

40 篇文章 0 订阅

Description

The procedure of Order Crossover (OX) applied in the Genetic Algorithm is as follows.

1. Select a substring from a parent at random.

2. Produce a proto-child by copying the substring into the corresponding position of it.

3. Delete the cities which are already in the substring from the 2nd parent. The resulted sequence of citires contains the cities that the proto-child needs.

4. Place the cities into the unfixed positions of the proto-child from left to right according to the order of the sequence to produce an offspring. 


Input

There may be multiple cases. For each case, the first line is an integer n (1<=n<=100). The second line and the third line give two parents(each line has ninteger). The fourth line gives the starting and ending position (x and y with 0<=x<=y<n) of the substring.

Output

For each case, output  two resultant offsprings.

问题解释:使用顺序交叉应用到遗传算法上。这里使用一组数代表一个个体,一个后代个体的产生由两个个体产生(暂且一个称A个体一个称B个体),其中一个个体会遗传一段连续的片段到子代相应的位置,剩下的子代内容则从另外一个个体中按照母个体的顺序获取。

输入:第一行表示每一个个体包含的数的个数(有点类似于DNA长度);第二行则是A个体的基因(一组由n个数组成的数);第三行则是B个体的基因;第四行表示从其中一个个体遗传基因的起止位置

输出:输出两种可能的子个体基因


#include <iostream>
#include <vector>
using namespace std;
static bool flag[100];
static int parent1[100],parent2[100];
//将输入的一组数变成数组
void getParent(int* a,int num){
    for(int i = 0; i <num; i ++){
        cin >> a[i];
    }
}
//获取子个体
void getOffspring(const int *p1,const int *p2,int begin,int end,int len,int* result){
    int i,j;
    //子个体从p1个体中获取从begin到end的一段序列
    for(i = begin; i <= end; i ++){
        flag[p1[i]] = true;
        result[i] = p1[i];
    }
    //子个体剩下的内容从p2个体中顺序获得
    for(i = 0,j = 0; i < len;i++ ){
        if(!flag[p2[i]]){
            if(j == begin) j = end +1;
            result[j] = p2[i];
            j ++;
        }
        else{
            flag[p2[i]] = false;
        }
    }
}
//输出子个体
void printVecInt(int *result,int len){
    for(int i = 0; i < len-1; i++){
        cout << result[i] << " ";
    }
    cout << result[len-1] << endl;
}

int main(int argc, const char * argv[]) {
    // insert code here...
    int Num;
    while(cin >> Num){
        if(Num == 0)break;
        int startPos,endPos;
        getParent(parent1, Num); //将输入的一组数转为数组
        getParent(parent2, Num);
        int offSpring1[100] ={0}, offSpring2[100]={0};
        cin >> startPos >> endPos;
        getOffspring(parent1, parent2, startPos, endPos,Num,offSpring1); //获取第一种情况的子个体
        getOffspring(parent2, parent1, startPos, endPos,Num,offSpring2); //获取第二种情况的子个体
        printVecInt(offSpring1,Num);
        printVecInt(offSpring2,Num);
    }
    return 0;
}                                 


后记:

因为要获得两种情况的子个体,可以写一个函数,改变输入参数顺序便可以获得两种情况。


代码新手,欢迎各位提出宝贵的建议和意见

如果要在不使用 `#include <unordered_set>` 的情况下实现类似功能,我们可以使用数组或列表来模拟邻接表,并使用位运算来标记已访问的箱子。这里是一个基于数组的解决方案: ```cpp #include <iostream> #include <vector> using namespace std; const int MAX_N = 100; // 假设箱子不超过100个 // 用一个布尔数组表示箱子是否被访问过,初始化全为false bool visited[MAX_N + 1]; // 定义邻接矩阵,使用二维数组表示箱子之间的钥匙关系 vector<vector<int>> graph(MAX_N + 1, vector<int>(MAX_N + 1)); void findUnlockable(int n, vector<int>& graph, vector<int>& result) { // 初始化遍历标志 for (int i = 0; i <= n; ++i) { visited[i] = false; } // 从第一个箱子开始,进行深度优先搜索 dfs(1, graph, result); } void dfs(int node, vector<int>& graph, vector<int>& result) { // 标记当前箱子已访问 visited[node] = true; // 添加当前箱子到结果中 result.push_back(node); // 遍历邻居节点 for (int nei : graph[node]) { // 如果邻居未被访问,则递归继续搜索 if (!visited[nei]) { dfs(nei, graph, result); } } } int main() { int n, m; cin >> n >> m; // 读取钥匙隐藏关系并更新邻接矩阵 for (int i = 0; i < m; ++i) { int u, v; cin >> u >> v; graph[u][v] = 1; // 表示箱子u的钥匙在箱子v中,这里的1只是一个标记 } vector<int> unlockable; // 用于存储结果 findUnlockable(n, graph, unlockable); // 输出结果 for (int box : unlockable) { cout << box << " "; } cout << endl; return 0; } ``` 请注意,这种方法仅适用于箱子数量较小的情况,因为数组大小是固定的,不适合大规模的数据。如果输入规模未知或者可能会很大,建议还是使用 `unordered_set` 或其他哈希集合来优化查找效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值