问题描述
一间教室里面如何安排灯的位置可以使房间地面的的照度均匀值达到最大!
C语言代码
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
#define length 10 //长
#define width 8 //宽
#define hight 4 //高
#define I 1 //灯照强度
#define N 16 //LED的数量
#define DEBUG
int LEDindex[N][2] =
{0};
//{12,11,6,5,2,16,8,11,12,2,2,2,2,3,10,2};
//{0,10,6,7,7,1,6,16,8,11,7,12,0,3,0,15};
//[[7,6],[9,0],[6,9],[10,8],[2,8],[0,11],[4,13],[1,9]]
int LEDindextemp[N][2]={0};
//._._.
int LED[width + 1][length + 1] = {0}; //LED存储位置
double space[width + 1][length + 1] = {0.0}; //储存每个地方的照明
double E[width + 1][length + 1][width + 1][length + 1] = {0}; //存储预先训练的光照数据,前两个为灯的位置,后两个为在该位置下灯对此处的照度值
double Umax = 0; //存储照度均匀度的最大值
int w = 0;
//struct LEDlocation{
// int x=0;
// int y=0;
//};
void pretrain() {
int i, j, s, t;
double r;
for (i = 0; i < width + 1; i++) {
for (j = 0; j < length + 1; j++) {
for (s = 0; s < width + 1; s++) {
for (t = 0; t < length + 1; t++) {
r = pow(hight, 2) + pow(i - s, 2) + pow(j - t, 2);
E[i][j][s][t] = I * hight / r;
}
}
}
}
printf("\npretrain finished!\n");
}
void clearLED() {
int i, j;
for (i = 0; i < width + 1; i++) {
for (j = 0; j < length + 1; j++) {
LED[i][j] = 0;
}
}
}
void randomLED(int n) {
clearLED();
srand(time(0));
int i, x, y;
for (i = 0; i < n; i++) {
x = rand() % (width + 1);
y = rand() % (length + 1);
if (LED[x][y] == 1) {
i--;
continue;
} else {
LED[x][y] = 1;
LEDindex[i][0] = x;
LEDindex[i][1] = y;
}
}
}
void calculateAllE() {
int i, j, s, t;
double r = 0.0;
for (i = 0; i < width + 1; i++) {
for (j = 0; j < length + 1; j++) {
space[i][j] = 0;
}
}
for (i = 0; i < N; i++) {
int x=LEDindex[i][0];
int y=LEDindex[i][1];
for (s = 0; s < width + 1; s++) {
for (t = 0; t < length + 1; t++) {
space[s][t] += E[x][y][s][t];
}
}
}
}
double calculateU() {
int i, j;
double Emin = space[0][0], Emax = space[0][0],Eaverage=0;
for (i = 0; i < width + 1; i++) {
for (j = 0; j < length + 1; j++) {
if (Emin > space[i][j]) {
Emin = space[i][j];
}
if (Emax < space[i][j]) {
Emax = space[i][j];
}
Eaverage+=space[i][j];
}
}
Eaverage=Eaverage/(width+1)/(length+1);
return Emin / Eaverage;
}
void displayLED() {
int i, j;
for (i = 0; i < width + 1; i++) {
for (j = 0; j < length + 1; j++) {
printf("%d ", LED[i][j]);
}
printf("\n");
}
}
void displayLEDSpace(){
int i;
int flag=sqrt(N);
for (i = 0; i < N; i++) {
cout<<"("<<LEDindex[i][0]<<","<<LEDindex[i][1]<<")";
if((i+1)%flag==0)
cout<<"\n";
}
cout<<"\n";
cout<<"[["<<LEDindex[0][0]<<","<<LEDindex[0][1]<<"]";
for (i = 1; i < N; i++) {
cout<<",["<<LEDindex[i][0]<<","<<LEDindex[i][1]<<"]";
}
cout<<"]\n";
}
void renewLED() {
clearLED();
for (int i=0;i<N;i++){
int x=LEDindex[i][0];
int y=LEDindex[i][1];
LED[x][y] = 1 ;
}
}
void findLEDbeyneighbor(int n) {
int i, j, x, y;
double u;
if (n == N ) {
w++;
calculateAllE();
u = calculateU();
if (u > Umax) {
Umax = u;
memcpy(LEDindextemp, LEDindex, sizeof(LEDindex));
}
} else {
x = LEDindex[n][0];
y = LEDindex[n][1];
findLEDbeyneighbor(n + 1);
if (x > 0 ) {
LEDindex[n][0]--;
findLEDbeyneighbor(n + 1);
LEDindex[n][0]++;
}
if (y > 0 ) {
LEDindex[n][1]--;
findLEDbeyneighbor(n + 1);
LEDindex[n][1]++;
}
if (x < width ) {
LEDindex[n][0]++;
findLEDbeyneighbor(n + 1);
LEDindex[n][0]--;
}
if (y < length ) {
LEDindex[n][1]++;
findLEDbeyneighbor(n + 1);
LEDindex[n][1]--;
}
}
}
bool compareX(int a[],int b[]){
return a[0]<=b[0];
}
bool compareY(int a[],int b[]){
return a[1]<=b[1];
}
void merge(int arr[][2], int low, int mid, int high,bool(*comper)(int[],int[])){
int i, k;
int total=high-low+1;
int **tmp = new int*[total];
for(i=0;i<total;i++)
tmp[i]=new int[2];
//申请空间,使其大小为两个
int left_low = low;
int left_high = mid;
int right_low = mid + 1;
int right_high = high;
for(k=0; left_low<=left_high && right_low<=right_high; k++){ // 比较两个指针所指向的元素
if(comper(arr[left_low],arr[right_low])){
tmp[k] = arr[left_low++];
}else{
tmp[k] = arr[right_low++];
}
}
if(left_low <= left_high){ //若第一个序列有剩余,直接复制出来粘到合并序列尾
//memcpy(tmp+k, arr+left_low, (left_high-left_low+l)*sizeof(int));
for(i=left_low;i<=left_high;i++)
tmp[k++] = arr[i];
}
if(right_low <= right_high){
//若第二个序列有剩余,直接复制出来粘到合并序列尾
//memcpy(tmp+k, arr+right_low, (right_high-right_low+1)*sizeof(int));
for(i=right_low; i<=right_high; i++)
tmp[k++] = arr[i];
}
for(i=0; i<high-low+1; i++)
{
// arr[low+i] = tmp[i];
}
free(tmp);
return;
}
void merge_sort(int arr[][2], unsigned int first, unsigned int last,bool(*compare)(int[],int[])){
int mid = 0;
if(first<last){
mid = (first+last)/2; /* 注意防止溢出 */
/*mid = first/2 + last/2;*/
//mid = (first & last) + ((first ^ last) >> 1);
merge_sort(arr, first, mid,compare);
merge_sort(arr, mid+1,last,compare);
merge(arr,first,mid,last,compare);
}
return;
}
int main() {
pretrain();
int i;
double tempu;
randomLED(N);
// merge_sort(LEDindex,0,N+1,compareX);
displayLEDSpace();
calculateAllE();
printf("Ustart : %lf\n", calculateU());
for (i = 0; i < 20; i++) {
findLEDbeyneighbor(0);
memcpy(LEDindex, LEDindextemp, sizeof(LEDindex));
// renewindex();
if (tempu == Umax) {
break;
} else {
tempu = Umax;
}
printf("w : %d , Umax : %lf\n", w, Umax);
}
displayLEDSpace();
renewLED();
displayLED();
calculateAllE();
printf("Uend : %lf\n", calculateU());
}