1. 程式人生 > >Fire Net ZOJ1002

Fire Net ZOJ1002

Analysis 我用的是遺傳演算法,步驟如下: 1.首先初始化個體,個體定義為題目中的n * n 的矩陣,然後blackhouse隨機分佈,生成50個這種個體。 2.適應度fitness:如果blackhouse的分佈滿足題目的要求,有x個blackhouse那麼適應度就為x,若有不滿足題目要求的分佈(同行或者同列),那麼適應度記為0。 3.選擇selector:對每個個體的適應度進行計算後從大到小排序,保留適應度前20的個體,作為倖存者,同時也是下一代的雙親。 4.交叉crossover:交叉方式是隨機選擇一行r,1行-r行來自於父親作為child的上半部分,r+1行-n行來自於母親作為child的下半部分。 5.變異mutation:變異只針對child,隨機選擇一個非’X’的地方,如果該處有blackhouse那麼移除它,如果沒有那就新增一個blackhouse。 6.更新群體,並且繼續迭代。 code

#include <iostream>
#include <algorithm>
#include <time.h>
#include <stdlib.h>
#include <vector>

#define pop_size 50
#define generation 30
#define SURVIVOR 20


struct chromosome{
    char c[4][4];
    int fitness;
    int emp ;
};     //染色體

bool compare(chromosome c1,chromosome c2){
    return c1.fitness > c2.fitness;
}


int get_fitness(chromosome individual,int n) ;                                              //計算適應度
chromosome Crossover(chromosome father,chromosome mother,int n);                            //交叉
void Mutation(chromosome &t,int n);                                                         //變異
 

int main(){
    int n;
    std::vector<int> score;
    std::cin>> n ;
    while(n!=0){
        // 初始化個體
        char board[n][n];
        chromosome individuals[pop_size];
        chromosome individual;
        individual.emp = 0;
        individual.fitness = 0;
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++) {
                std::cin >> board[i][j];
                if (board[i][j] == 'X'){
                    individual.c[i][j] = 'X';
                }
                else {individual.c[i][j] = 'N';individual.emp++;}

            }
        }

        for(int i=0;i<pop_size;i++)
            individuals[i] = individual;
        srand((unsigned)time(0));
        for(int i=0;i<pop_size;i++)
        {
            for(int j=0;j<n;j++)
            {
                for(int k=0;k<n;k++){
                    if(individuals[i].c[j][k] != 'X'){
                        if(rand() % n == 0) {
                            individuals[i].c[j][k] = 'Y';
                        }
                    }
                }
            }
        }
        // 初始化結束
        if(individuals[0].emp == 0) score.push_back(0);
        else{
            int g_count = 0;
            // start evolution
            while(g_count < generation)
            {
                for (int i = 0; i < pop_size; i++)
                    individuals[i].fitness = get_fitness(individuals[i], n);
                std::sort(individuals, individuals + pop_size, compare);

                chromosome survivor[SURVIVOR];
                chromosome next_generation[pop_size];
                int pop_count = 0;

                for ( ; pop_count < SURVIVOR ; pop_count++) {
                    survivor[pop_count] = individuals[pop_count];
                    next_generation[pop_count] = individuals[pop_count];
                }

                while (pop_count < pop_size)
                {
                    int f = rand() % SURVIVOR;
                    int m = rand() % SURVIVOR;
                    while(m == f) m = rand()%SURVIVOR;
                    chromosome temp;
                    temp = Crossover(survivor[f],survivor[m],n);
                    Mutation(temp,n);
                    next_generation[pop_count++] = temp;
                }

                for(int i=0;i<pop_size;i++)
                    individuals[i] = next_generation[i];
                g_count ++ ;
            }
            for (int i = 0; i < pop_size; i++)
                individuals[i].fitness = get_fitness(individuals[i], n);
            std::sort(individuals, individuals + pop_size, compare);
            int count = 0;
            for(int i=0;i<n;i++){
                for(int j=0;j<n;j++)
                    if(individuals[0].c[i][j] == 'Y')
                        count ++ ;

            }
            //    std::cout << count << std::endl;
            score.push_back(count);
        }
        std::cin >> n;
    }
    std::vector<int>::iterator it;
    for(it = score.begin();it != score.end();++it)
        std::cout<< *it << std::endl;
}



int get_fitness(chromosome individual,int n){
    int point = 0;
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            if(individual.c[i][j] == 'N' || individual.c[i][j] == 'X')
                continue;
            for(int k=i+1;k<n;k++){
                if(individual.c[k][j] == 'Y')
                    return 0;
                if(individual.c[k][j] == 'X')
                    break;
            }
            for(int k=j+1;k<n;k++){
                if(individual.c[i][k] == 'Y')
                    return 0;
                if(individual.c[i][k] == 'X')
                    break;
            }
            point ++ ;
        }
    }
    return point;
}

chromosome Crossover(chromosome father,chromosome mother,int n){
    chromosome child;
    int u = rand() % n;


    for(int i=0;i<u;i++){
        for(int j=0;j<n;j++)
            child.c[i][j] = father.c[i][j];
    }

    for(int i=u;i<n;i++){
        for(int j=0;j<n;j++)
            child.c[i][j] = mother.c[i][j];
    }
    return child;
}

void Mutation(chromosome &t,int n){
    int x_pos = rand() % n;
    int y_pos = rand() % n;

    while(t.c[x_pos][y_pos] == 'X'){
        x_pos = rand() % n;
        y_pos = rand() % n;
    }

    if(t.c[x_pos][y_pos] == 'N')  t.c[x_pos][y_pos] = 'Y';

    else t.c[x_pos][y_pos] = 'N';
    return ;
}