Fire Net ZOJ1002
阿新 • • 發佈:2018-12-11
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 ; }