The interface is very simple. There is only one "button1" button. After you press the button, the small circle in the large circle container is automatically moved to the local minimum value. If the conditions are not met, searches for a random position for the circle with the largest potential energy or the smallest potential energy, and re-calculates and moves the circle, the idea of this algorithm comes from Huang Wenqi and Xu Ruchu's "modern computing theory guidance-Background of NP hard problem, Prospect and Solution Algorithm Research" page 62.
Using system; using system. io; using system. collections; using system. collections. generic; using system. componentmodel; using system. data; using system. drawing; using system. LINQ; using system. text; using system. windows. forms; using system. threading; // form1.cs Packing Problem namespace packingob1 {public partial class form1: FORM {// Potential Energy // double step for progressive movement; circle [] circles = new circle [10]; streamread Er sr = new streamreader ("circles1.txt"); string line; int num; string [] r_str = new string [100]; string [] co_str = new string [200]; double [] radius = new double [100]; pointf [] cordinates = new pointf [100]; Public form1 () {initializecomponent ();} void drawcircle (circle) {graphics G = graphics. fromhwnd (this. handle); G. translatetransform (this. width/2, this. height/2); G. drawellipse (New Pen (color. black), new rectanglef (float) (circle. x-circle. r), (float) (circle. y-circle. r), (float) (2 * circle. r), (float) (2 * circle. r); G. dispose ();} void readstream (streamreader SR) {line = sr. readline (); num = convert. toint32 (line); // This is a covert class line = sr. readline (); r_str = line. split (New char [] {''}); // pay attention to the use of the split for (INT I = 0; I <num; I ++) {Radius [I] = convert. todouble (r_str [I]);} line = sr. readline (); co_str = line. split (New char [] {''}); For (INT I = 0; I <num; I ++) {cordinates [I]. X = (float) convert. todouble (co_str [2 * I]); cordinates [I]. y = (float) convert. todouble (co_str [2 * I + 1]);} private void form1_load (Object sender, eventargs e) {// read data from a text file, create a circular readstream (SR); For (INT I = 0; I <num; I ++) {circles [I] = New circle (); circles [I]. R = radius [I]; circles [I]. X = cordinates [I]. x; circles [I]. y = cordinates [I]. Y ;}}/// <summary> // calculate the potential energy of the entire system, max_pe for calculating the maximum potential energy and min_pe for the minimum potential energy at the same time // </Summary> double calc_pe (circle [] circles, ref circle maxpe_circle, ref circle minpe_circle) {double Pe = 0; // the previous calculation result is cleared before calculation !!! For (INT I = 1; I <num; I ++) {circles [I]. DX = 0; circles [I]. DY = 0; circles [I]. pe = 0;} calc_dx_dy (circles); For (INT I = 1; I <num; I ++) {PE + = circles [I]. PE;} maxpe_circle = minpe_circle = circles [1]; for (INT I = 2; I <num; I ++) {maxpe_circle = maxpe_circle.pe <circles [I]. PE? Circles [I]: maxpe_circle; minpe_circle = minpe_circle.pe> circles [I]. PE? Circles [I]: minpe_circle;} return PE ;} /// <summary> /// count Dx and dy of all circles /// </Summary> void calc_dx_dy (circle [] circles) {for (INT I = 1; I <num; I ++) {movedirection (circles [I], num, circles, I );}} /// <summary> /// calculate the direction of each circle to move /// </Summary> /// <Param name = "circle"> </param> // /<Param name = "num"> </param> // <Param name = "numth"> </param> void movedirection (circle, int num, circle [] C Ircles, int numth) {for (INT I = 0; I <num; I ++) {// consider the distance from 0th circles if (I = 0) {double d0i = math. SQRT (circle. x * circle. X + circle. y * circle. y); If (d0i + circle. r> circles [I]. r) {circle. dx + = circle. x/d0i * (d0i + circle. r-circles [I]. r); circle. dy + = circle. y/d0i * (d0i + circle. r-circles [I]. r); circle. PE + = math. pow (d0i + circle. r-circles [I]. r, 2.0) ;}/// consider the distance between the container and other circles else if (n Umth! = I) {double dij = math. SQRT (math. pow (circle. x-circles [I]. x, 2.0) + math. pow (circle. y-circles [I]. y, 2.0); If (dij <circle. R + circles [I]. r) {circle. dx + = (circles [I]. x-circle. x)/dij * (circle. R + circles [I]. r-dij); circle. dy + = (circles [I]. y-circle. y)/dij * (circle. R + circles [I]. r-dij); circle. PE + = math. pow (circle. R + circles [I]. r-dij, 2.0) ;}}} private void form1_paint (Object sender, painteventargs e) {for (INT I = 0; I <num; I ++) {drawcircle (circles [I]);} /// <summary> /// click, start to move the circle /// </Summary> /// <Param name = "sender"> </param> /// <Param name = "E"> </param> private void button#click (Object sender, eventargs e) {step = 0.1; Circle oldmaxpe = circles [0]; Circle maxpe = circles [1]; Circle minpe = circles [1]; double new_pe; double old_pe = 0; int T = 0; Wh Ile (true) {If (Step> = 0.001) {new_pe = calc_pe (circles, ref maxpe, ref minpe); If (new_pe <0.0001) {return ;} else if (new_pe <old_pe) {old_pe = new_pe; For (INT I = 1; I <num; I ++) {circles [I]. x-= Step * circles [I]. DX; circles [I]. y-= Step * circles [I]. dy;} invalidate (); Update (); // thread. sleep (10);} else if (new_pe> = old_pe) {old_pe = new_pe; step = 0.8 * step; For (INT I = 0; I <Num; I ++) {circles [I]. x-= Step * circles [I]. DX; circles [I]. y-= Step * circles [I]. dy;} invalidate (); Update (); // thread. sleep (10) ;}} else {If (maxpe = oldmaxpe) {T = t + 1;} If (T <1) {// random point selection on the disc, re-place the circle with the largest potential energy. // note that both maxpe and oldmaxpe point to the object in old_circles. Random Rand = new random (); maxpe. X =-circles [0]. R + 2 * circles [0]. R * Rand. nextdouble (); maxpe. y =-circles [0]. R + 2 * circles [0]. R * Rand. nextdouble (); oldmaxpe = maxpe; step = 0.1;} else if (t = 1) {random Rand = new random (); minpe. X =-circles [0]. R + 2 * circles [0]. R * Rand. nextdouble (); minpe. y =-circles [0]. R + 2 * circles [0]. R * Rand. nextdouble (); t = 0; oldmaxpe = circles [0]; step = 0.1 ;}}}/// <summary> // a circle accepts coordinates (x, y) and radius R // </Summary> public class circle {// The coordinates of the circle public Double X; Public Double Y; // the radius of the circle public Double R; // public double DX; Public double dy; Public double PE; // <summary> // create a circle (No parameter required) /// </Summary> Public circle () {This. DX = 0; this. DY = 0; this. pe = 0 ;} /// <summary> /// create a circle // </Summary> /// <Param name = "X"> </param> /// <Param name = "Y"> </param> // <Param name = "R"> </param> Public circle (Double X, double Y, double r) {This. X = x; this. y = y; this. R = r; this. DX = 0; this. DY = 0; this. pe = 0 ;} /// <summary> /// copy and copy the circle // </Summary> /// <returns> returns the circle </returns> Public circle clone () {circle clone_circle = new circle (); clone_circle.x = This. x; clone_circle.y = This. y; clone_circle.r = This. r; clone_circle.dx = This. DX; clone_circle.dy = This. dy; clone_circle.pe = This. PE; return clone_circle ;}}}