天地会的算法PK:小天的约会

AS3, 算法相关 | 2010年09月2日 下午 6:38 | RSS 2.0

什么,有好玩的编程问题?咱可就指着这个活呐。

这次纳兰出的是一个很美好的、帮助小天约会的题目。

原帖地址:http://bbs.9ria.com/thread-62598-1-1.html

简单说来,就是有n*n的一块地图,从其中一点出发,走遍地图上所有格子,求走法,再求共有多少种走法。

当然,算法是咱弱项,不可能像flashyiyi那样不到半小时就做出来。

不过既然要做,还是带个图比较好玩一些,取长补短吧:-)

经过了n久的努力……有了下面的小程序:

源代码:

import flash.display.Shape;
import flash.events.MouseEvent;
var LENGTH:uint=4;
var GIRDSIZE:uint=160/LENGTH;
var flags:Array;
var gird:Shape=addChild(new Shape()) as Shape;
var point:Shape=addChild(new Shape()) as Shape;
var track:Shape=addChild(new Shape()) as Shape;
var result:Array;
//Draw Gird
gird.graphics.lineStyle(1,0x666666);
for (var i:uint=0; i<LENGTH+1; i+=1) {
	gird.graphics.moveTo(5+i*GIRDSIZE,50);
	gird.graphics.lineTo(5+i*GIRDSIZE,210);
	gird.graphics.moveTo(5,50+i*GIRDSIZE);
	gird.graphics.lineTo(165,50+i*GIRDSIZE);
}
//Draw Point Rect;
point.graphics.beginFill(0xDD0000);
point.graphics.drawRect(6,51,GIRDSIZE-1,GIRDSIZE-1);
point.graphics.endFill();
point.visible=false;
stage.addEventListener(MouseEvent.CLICK,clickHandler);
function clickHandler(event:MouseEvent):void {
	if (event.stageX>5&&event.stageX<165&&event.stageY>50&&event.stageY<210) {
		var x:uint=(((event.stageX-5)/GIRDSIZE)>>0),y:uint=(((event.stageY-50)/GIRDSIZE)>>0);
		point.x=x*GIRDSIZE;
		point.y=y*GIRDSIZE;
		point.visible=true;
		calc(x,y);
	}
}
function createFlags():void {
	var length:uint=LENGTH+2;
	var border:uint=LENGTH+1;
	flags=new Array(length);
	for (var i:int=0; i<length; i+=1) {
		flags[i]=new Array(length);
		for (var j:int=0; j<length; j+=1) flags[i][j]=(i==0||j==0||i==border||j==border)?false:true;
	}
}
function calc(x:uint,y:uint):void {
	x=x+1,y=y+1;
	var next:Array=[{x:x,y:y}];
	createFlags();
	result=[];
	find(next);
	output.text=LENGTH+"*"+LENGTH+"的马场,解出"+result.length+"种路线";
	//trace(LENGTH+"*"+LENGTH+"的马场,解出"+result.length+"种路线");
	drawArgs(result[(Math.random()*result.length)>>0]);
}
function find(args:Array):void {
	var currentArg:Object=args[args.length-1];
	flags[currentArg.x][currentArg.y]=false;
	var next:Array=findNext(currentArg);
	var length:uint=next.length;
	if (length>0) {
		if (args.length>=LENGTH*LENGTH-1) {
			result.push(args.concat(next[0]));
		} else {
			for (var i:uint=0; i<length; i+=1) find(args.concat(next[i]));
		}
	}
	flags[currentArg.x][currentArg.y]=true;
}
function findNext(args:Object):Array {
	var x:uint=args.x,y:uint=args.y,res:Array=[];
	if (x>0&&flags[x-1][y]) res.push({x:x-1,y:y});
	if (y>0&&flags[x][y-1]) res.push({x:x,y:y-1});
	if (x<9&&flags[x+1][y]) res.push({x:x+1,y:y});
	if (y<9&&flags[x][y+1]) res.push({x:x,y:y+1});
	return res;
}
function copyFlags(array:Array):Array {
	var length=array.length;
	var result:Array=new Array(length);
	for (var i:int=0; i<length; i+=1) result[i]=array[i].concat();
	return result;
}
function drawArgs(array:Array):void {
	var length:int=array.length;
	var xOffset:uint=5+(GIRDSIZE>>1);
	var yOffset:uint=50+(GIRDSIZE>>1);
	track.graphics.clear();
	track.graphics.lineStyle(2,(Math.random()*0xFFFFFF)>>0);
	track.graphics.moveTo(xOffset+(array[0].x-1)*GIRDSIZE,yOffset+(array[0].y-1)*GIRDSIZE);
	for (var i:int=1; i<length; i+=1) {
		track.graphics.lineTo(xOffset+(array[i].x-1)*GIRDSIZE,yOffset+(array[i].y-1)*GIRDSIZE);
	}
}

这样的算法PK活动很好,可以让大脑多转一转。

不知道下次又会PK什么题目,小天和收银MM的未来又会走向何方?

我很期待。

后记:夜深人静,有些失眠,写写代码以放松身心。

整了一个纯位运算的效率最优版本:

var LENGTH:uint=4;
var COUNTLEN:uint=LENGTH*LENGTH-1;
var GIRDSIZE:uint=160/LENGTH;
var flags:Vector.<uint>;
var count:uint=0;
calc(3,3);
function createFlags():void {
	var length:uint=LENGTH+2;
	var border:uint=LENGTH+1;
	flags=new Vector.<uint>(32,true);
	for (var i:int=0; i<length; i+=1) {
		flags[i]=0x00000000;
		for (var j:int=0; j<length; j+=1) (i==0||j==0||i==border||j==border)?(flags[i]&=~(1<<j)):(flags[i]|=1<<j);
	}
}
function calc(x:uint,y:uint):void {
	createFlags();
	count=0;
	find(x+1,y+1,0);
	trace(LENGTH+"*"+LENGTH+"的马场,解出"+count+"种路线");
}
//无记录版,和flashyiyi的算法一样...
function find(x:uint,y:uint,c:uint):void {
	if((flags[x]>>y)&1){
		flags[x]&=~(1<<y);
		if (c>=COUNTLEN) {
			count+=1;
		} else {
			c+=1;
			find(x+1,y,c);
			find(x,y+1,c);
			find(x-1,y,c);
			find(x,y-1,c);
		}
		flags[x]|=1<<y;
	}
}

不过很不幸,位运算优化的版本在我电脑上也只能跑到6*6,机器好的可以试试看:-)

Tags: , ,

“天地会的算法PK:小天的约会” 目前只有 1 条回应

  1. Mutoo 说道:

    ACM啊ACM啊ACM啊

留下回复