RoBoard魔人的機器人日誌

2011/12/22

[練習] graph走訪程式

當一台機器人

想要讓他走到所有想讓他去的地方

那就需要利用走訪的程式

(本魔承認有點硬要扯到機器人...)

總之

來介紹一下兩種走訪方式



深度優先搜尋(depth - first search) 簡稱DFS

簡單的說就是先找到最深的路  再退回來走其他的路

像我的範例

若是用深度優先
他會從1 -> 2 -> 4 -> 3 然後沒路了   退回4  再走5     再往後退   都沒路就結束

以下為DFS的code

#include "stdafx.h"
#define graph_Max 5
void DFS(int);
static bool graph[graph_Max][graph_Max] = {
           {0,1,1,0,0},
           {1,0,0,1,0},
           {1,0,0,1,0},
           {0,1,1,0,1},
           {0,0,0,1,0}};
static int point_name[graph_Max] = {1,2,3,4,5};
int main(){
 DFS(0);
 getchar();
 return 0;
}
bool visited[graph_Max] = {false};
void DFS(int v){
 visited[v] = true;
 printf("%d\n",point_name[v]);
 for(int i = 0; i < graph_Max; i++)
  if(graph[v][i] && !visited[i])
   DFS(i);
}


廣度優先搜尋(breath - first search) 簡稱BFS

簡單的說就是將所有可走的路先走過  再走第二次...走到全部沒路為止
像我的範例

若是用廣度優先
他會從1 -> 2 & 3  然後1沒其他路   
2 -> 4  然後2沒其他路   
3 也沒其他路
再來到4 -> 5
最後的5  也沒路了    全部都沒路   結束


以下為BFS的code

#include "stdafx.h"
#define graph_Max 5
static bool graph[graph_Max][graph_Max] = {
           {0,1,1,0,0},
           {1,0,0,1,0},
           {1,0,0,1,0},
           {0,1,1,0,1},
           {0,0,0,1,0}};
static int point_name[graph_Max] = {1,2,3,4,5};
void BFS(int);
void push(int);
int pop();
bool isEmpty();
int main()
{
 BFS(0);
 getchar();
 return 0;
}
bool visited[graph_Max] = {false};
void BFS(int v){
 visited[v] = true;
 printf("%d\n",point_name[v]);
 for(int i = 0; i < graph_Max; i++)
  if(graph[v][i] && !visited[i]){
   visited[i] = true;
   push(i);
  }
 while(!isEmpty())
  BFS(pop());
}
int queue[graph_Max];
int first = 0;
int last = 0;
void push(int x){
 if(last >= graph_Max)
  last = 0;
 queue[last++] = x;
}
int pop(){
 return queue[first++];
}
bool isEmpty(){
 return first == last;
}



以上就是本魔這次介紹的兩個走訪程式
Share:

2011/12/16

[練習] 數獨程式


用NXT做的數獨機器人

前面比較繁瑣的工作是判斷位置

以及掃描出數字

將9*9表格讀入機器後就可以開始進行運算





藉此機會

就來研究看看解數獨的程式該如何寫吧

首先要瞭解規則

在1~9行內絕對只有1~9的數字 且不重複
在1~9列內絕對只有1~9的數字 且不重複
以每9格(正方) 為單位  9格內也只有1~9的數字 且不重複

例如:

1 2 3 4 5 6 7 8 9
4 5 6 7 8 9 1 2 3
7 8 9 1 2 3 4 5 6
2 3 4 5 6 7 8 9 1
5 6 7 8 9 1 2 3 4
8 9 1 2 3 4 5 6 7
3 4 5 6 7 8 9 1 2

這就算是一個數獨的答案

然而數獨的每個題目  永遠都只會有一個答案(如果有很多答案就沒什麼好玩了)










第一種解法:
利用佇列解
我是參考書上寫的
不過這方法似乎只能解基本的數獨
因為他是將未填入數字的位置 存入佇列中
再一一拿出來做

因為有一些數獨是需要用判斷的才能解
所以這種解法可能無法適用於所有的題目




#include <stdio.h>
struct data_item{
 int x,y,val;
};
struct sudoku_item{
 int x,y;
 int num;
 int val[10];
 int resVal;
};
sudoku_item sudoku[9][9];
int rear,front;
data_item *dataQ[9*9];
void createQueue(){
   rear = front = 0;
}
void enque(data_item *dataItem){
 dataQ[rear] = dataItem;
 rear = (rear +1) % (9*9);
}
data_item *deque(){
 data_item *dataItem = dataQ[front];
 front = (front + 1)% (9*9);
 return dataItem;
}
int isEmpty(){
 return rear == front;
}
data_item *clrSudokuItem(int x, int y, int n){
 data_item *dataItem;
 int i;
 if(sudoku[x][y].resVal == 0){
  sudoku[x][y].num-= sudoku[x][y].val[n];
  sudoku[x][y].val[n] = 0;
  if(sudoku[x][y].num == 1)
   for(i = 1; i < 10; i++)
    if(sudoku[x][y].val[i] == 1){
     sudoku[x][y].resVal = i;
     dataItem = (data_item *) new data_item;
     dataItem ->x = x;
     dataItem ->y = y;
     dataItem ->val = i;
     return dataItem;
    }
 }
 return NULL;
}
void preprocess(int dataArr[][9]){
 data_item *dataItem;
 int i,j,k;
 createQueue();
 for(i = 0; i < 9;i++){
  for(j = 0; j< 9; j++){
   printf("%d ",dataArr[i][j]);
   if(dataArr[i][j] != 0){
    sudoku[i][j].num = 1;
    sudoku[i][j].resVal = dataArr[i][j];
    dataItem = (data_item *) new data_item;

    dataItem->x = i;
    dataItem->y = j;
    dataItem->val = dataArr[i][j];
    enque(dataItem);
   }else{
    sudoku[i][j].x = i;
    sudoku[i][j].y = i;
    for(k = 1; k<10; k++)
     sudoku[i][j].val[k] = 1;
    sudoku[i][j].num = 9;
    sudoku[i][j].resVal = 0;
   }
  }
  printf("\n");
 }
}
void processSudoku(){
 data_item *dataItem,*retData;
 int i,j;
 while(!isEmpty()){
  int x,y,val;
  dataItem = deque();
  x =dataItem->x;
  y =dataItem->y;
  val = dataItem->val;
  for(i = 0; i<9; i++){
   if(i != y){
    retData = clrSudokuItem(x,i,val);
    if(retData != NULL)
     enque(retData);
   }
   if(i != x){
    retData = clrSudokuItem(i,y,val);
    if(retData != NULL)
     enque(retData);
   }
  }
  for(i = 0; i<3; i++)
   for(j = 0; j<3; j++){
    int m = x/3 *3 +i;
    int n = y/3 *3 +j;
    if(m!=x && n != y){
     retData = clrSudokuItem(m,n,val);
     if(retData != NULL)
      enque(retData);
    }
   }
 }
}
void output(){
 int i,j;
 printf("Answer:\n");
 for(i = 0; i<9; i++){
  for(j = 0; j<9; j++)
   printf("%d ",sudoku[i][j].resVal);
  printf("\n");
 }
}
int main(){
 int data[9][9] = {
  {3,0,1,0,0,9,0,5,0},
  {0,9,0,0,0,4,1,8,0},
  {0,0,0,6,2,0,9,0,4},
  {1,0,0,0,4,0,0,6,0},
  {0,5,0,0,6,0,0,4,0},
  {0,8,0,9,7,0,5,0,2},
  {0,0,5,0,3,2,0,0,0},
  {0,2,9,0,0,0,0,0,5},
  {0,6,0,5,9,0,4,0,0}};
 preprocess(data);
 processSudoku();
 output();
 getchar();
 return 0;
}







第二種解法:
第二次我是利用遞迴讓所有可能性直接跑完(直到有答案)
相信大家都知道遞迴的缺點 浪費時間,空間
不過我還沒想到可以縮短執行時間,空間的方法
若有 歡迎指教

#include "stdafx.h"
struct local_mark{
 int x[9];
 int y[9];
 int z[9];
};
struct point{
 int x;
 int y;
};
local_mark *Number_Place_set(int [][9]);
bool Number_Place_game(int [][9], local_mark *);
int local_val(int, int);
int bitcount(int );
void print_data(int [][9]);
int main(){ 
 int data[9][9] = {
     {3,0,1,0,0,9,0,5,0},
     {0,9,0,0,0,4,1,8,0},
     {0,0,0,6,2,0,9,0,4},
     {1,0,0,0,4,0,0,6,0},
     {0,5,0,0,6,0,0,4,0},
     {0,8,0,9,7,0,5,0,2},
     {0,0,5,0,3,2,0,0,0},
     {0,2,9,0,0,0,0,0,5},
     {0,6,0,5,9,0,4,0,0}};
 printf("Subject:\n");
 print_data(data);
 local_mark *mark = Number_Place_set(data);
 printf("Answer:\n");
 if(Number_Place_game(data,mark)){
  print_data(data);
 }else{
  printf("No solution!\n");
 } 

 getchar();
 return 0;
}

local_mark *Number_Place_set(int data[][9]){
 local_mark *mark = (local_mark*) new local_mark;
 for(int i = 0; i < 9; i++ )
  mark -> x[i] = mark -> y[i] = mark -> z[i] = 0;
 for(int i = 0; i < 9; i++ )
  for(int j = 0; j < 9; j++)
   if(data[i][j]){
    mark -> x[j] |= (1 << data[i][j]-1);
    mark -> y[i] |= (1 << data[i][j]-1);
    mark -> z[local_val(i,j)] |= (1 << data[i][j]-1);
   }
 return mark;
}
bool Number_Place_game(int data[][9], local_mark *mark){
 point *p = (point*) new point;
 int m , max = 0 , count = 0;
 for(int i = 0; i < 9; i++ )
  for(int j = 0; j < 9; j++)
   if(!data[i][j]){
    count++;
    m = mark->x[j] | mark->y[i] | mark->z[local_val(i,j)];
    if(bitcount(m) > bitcount(max)){
     max = m;
     p -> x = j;
     p -> y = i;
    }
   }
 if(count == 0)
  return true;
 for(int i = 0; i < 9; i++)
  if(max != (max | (1 << i))){
   data[ p->y ][ p->x ] = i+1;
   mark -> x[ p->x ] |= (1 << i);
   mark -> y[ p->y ] |= (1 << i);
   mark -> z[ local_val( p->y , p->x ) ] |= (1 << i);
   if(Number_Place_game(data,mark)){
    return true;
   }else{
    data[ p->y ][ p->x ] = 0;
    mark -> x[ p->x ] &= ~(1 << i);
    mark -> y[ p->y ] &= ~(1 << i);
    mark -> z[ local_val( p->y , p->x ) ] &= ~(1 << i);
   }
  }
 return false;
}
int local_val(int x,int y){
 return y/3+(x/3)*3;
}
int bitcount(int x){
 int b;
 for(b = 0; x; x &= x-1)
  ++b;
 return b;
}
void print_data(int data[][9]){
 for(int i = 0; i < 9; i++){
  for(int j = 0; j < 9; j++)
   printf("%d ",data[i][j]);
  printf("\n");
 }
}

Share:

2011/12/8

[推薦] 在blogger裡使用google-code-prettify

我想會來到魔人這邊的訪客大部分應該都對機器人有興趣

甚至有已經接觸過機器人的吧?

成品作出來之後當然會想拿出來和大家分享囉!!

機器人免不了要經過coding的過程

所以這邊推薦一個蠻好用的程式碼高亮度顯示程式



安裝步驟按照下面作計可以囉~


首先到Blogger的[資訊主頁]   選擇[設計]

然後找到[修改HTML] 將以下所有內容貼至<head>至</head>之間

<link href='http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css' type='text/css' rel='stylesheet' />
<script type='text/javascript' src='http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js'></script>





















下一個步驟必須要找到<body> 然後再onload的事件加入prettyPrint();

找不到<body>的話可以直接用搜尋(ctrl+F) 找"<body"字串



onload='prettyPrint()'



















做完以上的步驟之後就可以在你的文章中貼漂亮的程式碼囉

不過貼了之後  還要到原始碼模式

在程式碼前後加上
<pre class="prettyprint">
//這邊貼程式碼
</pre>


還有必須注意的一點為

程式碼不可在原始碼模式下直接貼上

否則原始碼模式會把& < >字元吃掉

在原始碼模式下
“&” 需轉換為 “&amp;”
”<” 需轉換為 “&lt;”
”>” 需轉換為 “&gt;”



貼個小範例程式吧!
#include "stdio.h"
int main(){
   printf("Hello, World!");
   getchar();
   return 0;
}
Share:
技術提供:Blogger.

追蹤者