數據結構PTA(浙大mooc)


                                               04-樹5 Root of AVL Tree (25分)

An AVL tree is a self-balancing binary search tree. In an AVL tree, the heights of the two child subtrees of any node differ by at most one; if at any time they differ by more than one, rebalancing is done to restore this property. Figures 1-4 illustrate the rotation rules.

 

 

Now given a sequence of insertions, you are supposed to tell the root of the resulting AVL tree.

 

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive integer N (20) which is the total number of keys to be inserted.

Then N distinct integer keys are given in the next line. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print the root of the resulting AVL tree in one line.

Sample Input 1:

5
88 70 61 96 120
 

Sample Output 1:

70
 

Sample Input 2:

7 88 70 61 96 120 90 65 
 

Sample Output 2:

88
#include<stdio.h>
#include<malloc.h>
#define EH 0 //等高
#define RH -1 //右高
#define LH 1 //左高
typedef struct BSTNode *BSTree;




void L_Rotate(BSTree &p);
void R_Rotate(BSTree &p);
void LeftBalance(BSTree &T);
void RightBalance(BSTree &T);
int InsertAVL(BSTree &T, int e, bool &taller);
struct BSTNode
{
    int data;
    int bf;  //-1代表右高,1代表左高,0代表左右一樣高
    BSTree lchild;
    BSTree rchild;
};

int main()
{
    int n;
    scanf_s("%d", &n);
    int x;
    BSTree T=NULL;
    bool taller = false;
    for (int i = 0; i < n; i++)
    {
        scanf_s("%d", &x);
        InsertAVL(T, x, taller);
    }
    printf("%d\n", T->data);
    return 0;
}


//右旋
void R_Rotate(BSTree &p)
{
    BSTree lc;
    lc = p->lchild;      //lc指向p的左子樹的根結點
    p->lchild = lc->rchild;  //p的左子樹接lc的右子樹
    lc->rchild = p;    //lc的右子樹接p
    p = lc;         //p指向新的根結點
}

//左旋
void L_Rotate(BSTree &p)
{
    BSTree rc = p->rchild;   //rc指向p的右子樹的根結點
    p->rchild = rc->lchild;  //p的右子樹接rc的左子樹
    rc->lchild = p;           //rc的左子樹接為p
    p = rc;           //p指向新的根結點
}

int InsertAVL(BSTree &T, int e, bool &taller)
{
    //若在平衡的二叉搜索樹T中不存在和e相同的結點則插入一個新結點,返回1,否則返回0
    //若因插入使二叉搜索樹失去平衡,則做平衡旋轉處理,bool類型判斷T是否長高
    if (!T){//插入新結點,樹長高,taller置為True
        T = (BSTree)malloc(sizeof(BSTNode));
        T->data = e;
        T->lchild = T->rchild = NULL;
        T->bf = EH;
        taller = true;
    }
    else
    {
        if (e == T->data) //存在和e相同的結點不插入
        {
            taller = false;
            return 0;
        }
        if (e < T->data)     //應在T的左子樹中進行搜索
        {
            if (!InsertAVL(T->lchild, e, taller)) //返回值為0說明左子樹中存在相同的結點,則直接return 0;
                return 0;
            if (taller)    //如果樹長高了,判斷是否需要平衡
            {
                switch (T->bf)    //檢查T的平衡因子
                {
                case LH:                          //原來左子樹比右子數高,又插入在左子樹中,需要做平衡
                    LeftBalance(T); taller = false; break;
                case EH:
                    T->bf = LH; taller = true;
                    break;
                case RH:
                    T->bf = EH; taller = false; break;
                }
            }
        }
        else                                 //在T的右子樹種進行搜索
        {
            if (!InsertAVL(T->rchild, e, taller))    //返回值為0,說明右子樹種存在相同的結點,不用插入
                return 0;
            if (taller)
            {
                switch (T->bf)
                {
                case LH:
                    T->bf = EH; taller = false; break;
                case EH:
                    T->bf = RH; taller = true; break;
                case RH:
                    RightBalance(T); taller = false; break;
                }
            }
        }
        
    }
    return 1;
}

void LeftBalance(BSTree &T)
{
    //對以T為根結點的二叉樹做左平衡旋轉,結束后,指針T指向新的根結點
    BSTree lc = T->lchild;
    switch (lc->bf)           //檢查T的左子樹的平衡因子
    {
    case LH:          //如果左邊高,則做右旋操作
        T->bf = lc->bf = EH;       //先修改平衡因子,右旋后,平衡因子置為EH
        R_Rotate(T); break;
    case RH:          //如果右高,新結點插在T的左子樹的右子樹上,應做左右雙旋
        BSTree rd = lc->rchild;
        switch (rd->bf)     //按照三種情況修改,T和lc的平衡因子
        {
        case LH:lc->bf = EH; T->bf = RH; break;
        case EH:lc->bf = T->bf = EH; break;
        case RH:T->bf = EH; lc->bf = LH; break;
        }
        rd->bf = EH;  //修改rd的平衡因子
        L_Rotate(T->lchild);    //對T的左子樹進行左旋,旋轉之后T的左孩子變為rd;
            R_Rotate(T);       //然后對T進行右旋操作
            break;

    }
}

void RightBalance(BSTree &T)
{
    BSTree rc = T->rchild;   //rc指向T的右子樹
    switch (rc->bf)
    {
    case RH:    //插入在T的右子樹的右子樹上,應進行右旋操作
        T->bf = rc->bf = EH;//先修改T和T的右子樹的平衡因子
        L_Rotate(T); break;
    case LH:    //插入在T的右子樹的左子樹上,應進行右左雙選操作
        BSTree ld = rc->lchild;
        switch (ld->bf)
        {
        case LH:T->bf = EH; rc->bf = RH; break;
        case EH:T->bf = rc->bf = EH;  break;
        case RH:T->bf = LH; rc->bf = EH; break;
        }
        ld->bf = EH;
        R_Rotate(T->rchild);    //對T的右子樹進行右旋,旋轉后T的右子樹的根結點變成ld
        L_Rotate(T);       //然后對T進行左旋
        break;
    }
}

 

 

 

/*分析:
完全二叉搜索樹,滿足二叉搜索樹的性質也滿足完全二叉樹的性質,畫圖可以知道,右邊的值都比左邊的大
可以先排個序,每個根結點的值排的位置都是左子樹的個數,加上他左邊的結點的個數.





#include<stdio.h> #include<math.h> #include<stdlib.h> #define Maxsize 1000 typedef struct TNode *BSTree; int a[1000]; struct TNode { int data; BSTree left; BSTree right; }; //隊列的順序存儲 struct QNode { BSTree *bst; int front, rear; int maxsize; }; typedef struct QNode *Queue; Queue CreateQueue() { Queue Q = (Queue)malloc(sizeof(struct QNode)); Q->bst = (BSTree *)malloc(Maxsize*sizeof(struct TNode)); Q->front = Q->rear = 0; Q->maxsize = Maxsize; return Q; } int IsEmpty(Queue Q) { if (Q->front == Q->rear) return 1; else return 0; } //選擇排序 void sort(int a[], int n) { for (int i = 0; i<n; i++) { for (int j = i + 1; j<n; j++) { if (a[i]>a[j]) { int tmp = a[i]; a[i] = a[j]; a[j] = tmp; } } } } //求左子樹結點的個數 int LeftNum(int n) { int k=0;// n個結點的樹的層數 int m=1; //m-1表示k層滿二叉樹的結點個數 int p;//表示左子樹結點的個數 while (m < n + 1) { m = 2 * m; k++; } if (m - 1 - (int)pow(2.0, k - 2) <= n) //左子樹是滿的 { p = (int)(pow(2.0, k - 1)) - 1; } else p = n - (int)pow(2.0, k - 2); return p; } BSTree Insert(int left, int n, BSTree T); void preOrderTravasel(BSTree T); void LevelTravasel(BSTree T); int main() { int n; scanf("%d", &n); for (int i = 0; i<n; i++) { scanf("%d", &a[i]); } //從小到大排序 sort(a, n); BSTree T=NULL; T=Insert(0, n,T); //preOrderTravasel(T); LevelTravasel(T); printf("\n"); return 0; } void preOrderTravasel(BSTree T) { if (T != NULL) { printf("%d ", T->data); preOrderTravasel(T->left); preOrderTravasel(T->right); } } BSTree Insert(int left, int n, BSTree T) { if (n == 0) return NULL; T = (BSTree)malloc(sizeof(struct TNode)); int p = LeftNum(n); //左子樹的個數 int m = n - p-1; //右子樹的個數 T->data = a[p + left]; T->left = Insert(left, p, T->left); T->right = Insert(left + p + 1, m, T->right); return T; } void LevelTravasel(BSTree T) { Queue Q = CreateQueue(); Q->bst[Q->rear++] = T; int i = 0; while (IsEmpty(Q) == 0) { T = Q->bst[Q->front++]; if (i++ == 0) printf("%d", T->data); else printf(" %d", T->data); if (T->left != NULL) { Q->bst[Q->rear++] = T->left; } if (T->right != NULL) { Q->bst[Q->rear++] = T->right; } } }

 

Sample Input:

7
A 1 B 1 C 1 D 3 E 3 F 6 G 6
4
A 00000
B 00001
C 0001
D 001
E 01
F 10
G 11
A 01010
B 01011
C 0100
D 011
E 10
F 11
G 00
A 000
B 001
C 010
D 011
E 100
F 101
G 110
A 00000
B 00001
C 0001
D 001
E 00
F 10
G 11

 

#include<stdio.h>
#include<malloc.h>
#include<string.h>

//分析:
//判斷是否是最優解,其實就是判斷wpl是否最小
//加上沒有二義性,需要是前綴碼
//算法思路:根據輸入的,建立一個哈夫曼樹,尋找兩個最小的值,然后插入需要借助堆,然后求出最小的wpl.判斷輸入的每一組數據是否是前綴碼和wpl最小
int value[256]; //哈夫曼樹的定義 typedef struct TreeNode *HuffmanTree; typedef struct TreeNode { int weight; char data; HuffmanTree left, right; }Node; //最小堆 typedef struct TNode { HuffmanTree *data; int size; }*MinHeap; void Insert(int n, HuffmanTree T, MinHeap H); //最小堆插入 HuffmanTree Delete(MinHeap H); //最小堆刪除 HuffmanTree BuildHuffman(MinHeap H); //建一個哈夫曼樹 int Judge(int n, int totalspace); //判斷是否是最右鍵 int WPL(HuffmanTree T, int Depth); //求wpl int main() { MinHeap H = (MinHeap)malloc(sizeof(struct TNode)); H->data = (HuffmanTree *)malloc(1001 * sizeof(HuffmanTree)); H->size = 0; //哨兵 HuffmanTree a = (HuffmanTree)malloc(sizeof(struct TreeNode)); a->weight = -1000; H->data[0] = a; int n; scanf_s("%d\n", &n); //生成一個最小堆 for (int i = 0; i<n; i++) { Insert(1, NULL, H); } //建一個哈夫曼樹 HuffmanTree T = BuildHuffman(H); //計算哈夫曼樹形成的哈夫曼編碼的最小wpl int Space = WPL(T,0); int m; scanf_s("%d", &m); getchar(); for (int i = 0; i<m; i++) { int sum; //輸入的編碼的wpl和最優的比較 sum=Judge(n,Space); if (sum == Space) printf("Yes\n"); else printf("No\n"); } } //最小堆的插入 void Insert(int n, HuffmanTree T, MinHeap H) { if (n == 1){ //當n=1時,是輸入,建一個最小堆 char c; int weight; scanf_s("%c %d", &c, 1, &weight); int index = c; //將字母的權重存起來 value[index] = weight; getchar(); T = (Node *)malloc(sizeof(struct TreeNode)); T->weight = weight; T->data = c; T->left = NULL; T->right = NULL; int i = ++H->size; for (; H->data[i / 2]->weight>weight; i /= 2) { //向上過濾 H->data[i] = H->data[i / 2]; } //將T插入 H->data[i] = T; } else if (n == 2){ //n=2是插入一個結點 int i = ++H->size; for (; H->data[i / 2]->weight>T->weight; i /= 2){ H->data[i] = H->data[i / 2]; } H->data[i] = T; } } int WPL(HuffmanTree T, int Depth) { /* 整棵樹的WPL */ if (!T->left && !T->left) { return Depth*T->weight; } else return WPL(T->left, Depth + 1) + WPL(T->right, Depth + 1); } //刪除最小堆的堆頂元素 HuffmanTree Delete(MinHeap H) { HuffmanTree min = H->data[1]; //保存最后一個元素 int temp = H->size--; int child, parent; parent = 1; for (; parent * 2 <= H->size; parent = child) { //向下過濾,尋找要插入的位置 child = parent * 2; //找左右小的 if (child != H->size&&H->data[child + 1]->weight < H->data[child]->weight) { child++; } if (H->data[child]->weight >= H->data[temp]->weight) break; else { H->data[parent] = H->data[child]; } } //插入最后一個元素 H->data[parent] = H->data[temp]; return min; } //判斷是否是最優解 int Judge(int n, int totalspace) { char c; char a[63]; char **str = (char **)malloc(n * 63 * sizeof(char)); for (int i = 0; i < n; i++) { //給n個字符串開辟空間 str[i] = (char *)malloc(63 * sizeof(char)); } int sum = 0; for (int i = 0; i < n; i++) { scanf_s("%c", &c, 1); getchar(); a[i] = c; scanf_s("%s", str[i], 63); getchar(); } //計算wpl for (int i = 0; i < n; i++) { sum += value[a[i]] * strlen(str[i]); } if (totalspace != sum) return -1; //字符串按長度排序 for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { if (strlen(str[i])>strlen(str[j])) { char *p = str[i]; str[i] = str[j]; str[j] = p; char t = a[i]; a[i] = a[j]; a[j] = t; } } } //判斷是否是前綴碼 for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { int flag = 1; if (strlen(str[i]) == strlen(str[j])) { if (strcmp(str[i], str[j]) == 0) return -1; continue; } for (int k = 0; k < strlen(str[i]); k++) { if (str[i][k] != str[j][k]) { flag = 0; break; } } if (flag == 1) return -1; } } return sum; } //生成一個哈夫曼樹 HuffmanTree BuildHuffman(MinHeap H) { int i; HuffmanTree T; int size = H->size; if (H->size == 1) { T = (HuffmanTree)malloc(sizeof(struct TreeNode)); T->weight = H->data[1]->weight; T->left = (HuffmanTree)malloc(sizeof(struct TreeNode)); T->left->weight = H->data[1]->weight; T->right = NULL; T->left->left = NULL; T->left->right = NULL; return T; } for (i = 1; i<size; i++) { //直到,堆中只有一個元素 T = (HuffmanTree)malloc(sizeof(struct TreeNode)); //取出兩個最小的值 T->left = Delete(H); T->right = Delete(H); //加起來后,插進去 T->weight = T->left->weight + T->right->weight; Insert(2, T, H); } //取出堆頂元素 T = Delete(H); return T;
}

 

 

 

Sample Input 1:

5
C 3 2
I 3 2
C 1 5
I 4 5
I 2 4
C 3 5
S
 

Sample Output 1:

no
no
yes
There are 2 components.

Sample Input 2:

5 C 3 2 I 3 2 C 1 5 I 4 5 I 2 4 C 3 5 I 1 3 C 1 5 S 
 

Sample Output 2:

no no yes yes The network is connected.
#include<stdio.h>
#include<malloc.h>
#define MAXN 1000                  /* 集合最大元素個數 */
typedef int ElementType;           /* 默認元素可以用非負整數表示 */
typedef int SetName;               /* 默認用根結點的下標作為集合名稱 */
typedef ElementType SetType[MAXN]; /* 假設集合元素下標從0開始 */

void Union(SetType S, SetName Root1, SetName Root2)
{ 

    //按秩歸並
    //把元素少的集合連在元素多的上,可以降低樹的高度
    if (S[Root2] > S[Root1])
    {
        S[Root1] += S[Root2];
        S[Root2] = Root1;
    }
    else if (S[Root1] > S[Root2])
    {
        S[Root2] += S[Root1];
        S[Root1] = Root2;
    }
}

SetName Find(SetType S, ElementType X)
{ /* 默認集合元素全部初始化為-1 */
    if (S[X] < 0) /* 找到集合的根 */
        return X;
    else
        return S[X] = Find(S, S[X]); /* 路徑壓縮 */  //也是吧每一個路徑上的元素,都直接連上根結點上,這樣樹的高度就降低了
}

void Initial(SetType S, int n);     //將集合中的每一個結點的parent置為-1
void Input_connection(SetType S);     
void Check_connection(SetType S);
void Check_network(SetType S, int n);
int main()
{
    
    SetType S;
    int  n;
    char in;
    //初始化集合
    scanf_s("%d",&n);
    Initial(S, n);
    do{
        scanf_s("%c", &in);
        switch (in){
        case 'I':Input_connection(S); break;
        case 'C':Check_connection(S); break;
        case 'S':Check_network(S, n);
        }
    } while (in!='S');
    return 0;
}
void Initial(SetType S, int n)
{
    for (int i = 0; i < n; i++)
    {
        S[i]=-1;
    }
}
void Input_connection(SetType S)
{
    int u, v;
    int root1, root2;
    scanf_s("%d %d\n", &u, &v);
    //輸入兩個元素,然后找到,這兩個元素的各自的集合,進行合並
    root1 = Find(S, u - 1);
    root2 = Find(S, v - 1);
    Union(S, root1, root2);
}
void Check_connection(SetType S)
{
    //檢查兩個元素是否在同一個集合中
    int u, v;
    int root1, root2;
    scanf_s("%d %d\n", &u, &v);
    //查找兩個元素的根,是否是同一個結點
    root1 = Find(S, u - 1);
    root2 = Find(S, v - 1);
    if (root1 == root2)
        printf("yes\n");
    else printf("no\n");
}
void Check_network(SetType S, int n)
{
    //判斷所有元素是否在同一個集合上
    //小於0的只有一個,即只有一個集合,小於0的多個就有多個集合
    int i,counter = 0;
    for (i = 0; i < n; i++)
    {
        if (S[i] < 0) counter++;
    }
    if (counter == 1) printf("The network is connected.\n");
    else printf("There are %d components.\n", counter);
}

 

 

 

 

#include<stdio.h>

//最小堆
int MinH[1001];
//size表示當前的最后一個結點的位置
int size = 0;
void Insert(int x);
void LuJin(int index);
int main()
{
    MinH[0] = -10001;
    int n, m;
    scanf_s("%d %d", &n, &m);
    for (int i = 0; i < n; i++)
    {
        int x;
        scanf_s("%d", &x);
        Insert(x);
    }
    for (int i = 0; i < m; i++)
    {
        int index;
        scanf_s("%d", &index);
        LuJin(index);
    }
}
//插入
void Insert(int x)
{
    //要插入最后一個元素的位置
    int i = ++size;
    for (; MinH[i / 2] > x; i /= 2)
    {
        //一直向上找
        MinH[i] = MinH[i / 2];
    }
    //找到后插入
    MinH[i] = x;
}

void LuJin(int index)
{
    int root = index;
    for (; root != 0; root /= 2)
    {
        if (root == index)
            printf("%d", MinH[root]);
        else
            printf(" %d", MinH[root]);
    }
    printf("\n");
}

 

 

 

#include<stdio.h>
#include<malloc.h>

//采用鄰接表來表示圖
/*算法思路:
先通過鄰接表建一個圖,建圖時,需主要,題目要求從小到大,
故,每個鏈表都需要升序來排,不能直接頭插了
然后先深度優先遍歷,不連通的話,還需要一個for循環,
保證每個結點都被訪問過,類似樹的先序遍歷
然后是廣度優先遍歷,類似樹的層次遍歷,需要隊列*/


typedef
struct node *List; typedef struct node *Node; struct node{ int V;//在數組中的下標 int weight; Node next; }; typedef struct VNode *PtrVNode; typedef struct VNode{ List firstEdge; }AdjList[1000]; AdjList G; int Nv; int Ne; int Visited[1000]; void visit(int Vertex) { printf("%d ", Vertex); } //定義隊列 typedef struct queue{ int data[1000]; int front; int rear; int maxsize; }*Queue; Queue CreateQueue() { Queue Q = (Queue)malloc(sizeof(struct queue)); Q->front = Q->rear = 0; Q->maxsize = 1000; return Q; } void addQ(Queue Q, int x) { Q->data[Q->rear++] = x; } int DeleteQ(Queue Q) { return Q->data[Q->front++]; } int IsEmpty(Queue Q) { if (Q->front == Q->rear) return 1; else return 0; } void DFS(int V); void BFS(int V); int main() { scanf_s("%d %d", &Nv, &Ne); //初始化0條邊,Nv個結點的圖 for (int i = 0; i < Nv; i++) { G[i].firstEdge = NULL; } //插入Ne條邊 int v1, v2, weight = 1; Node p; for (int i = 0; i < Ne; i++) { scanf_s("%d %d", &v1, &v2, &weight); //將v2插入到v1的鏈表中 Node NewNode = (Node)malloc(sizeof(struct node)); NewNode->V = v2; NewNode->weight = weight; if (G[v1].firstEdge == NULL) { NewNode->next = G[v1].firstEdge; G[v1].firstEdge = NewNode; } else{ p = G[v1].firstEdge; //鏈表升序 //尋找要插入的位置 if (v2 < p->V) { NewNode->next = G[v1].firstEdge; G[v1].firstEdge = NewNode; } else{ while (p->next != NULL&&v2 > p->next->V) p = p->next; //插入 NewNode->next = p->next; p->next = NewNode; } } //無向圖,還需將v1插入到v2中 NewNode = (Node)malloc(sizeof(struct node)); NewNode->V = v1; NewNode->weight = weight; if (G[v2].firstEdge == NULL) { NewNode->next = G[v2].firstEdge; G[v2].firstEdge = NewNode; } else{ p = G[v2].firstEdge; //鏈表升序 //尋找要插入的位置 if (v1 < p->V) { NewNode->next = G[v2].firstEdge; G[v2].firstEdge = NewNode; } else{ while (p->next != NULL&&v1 > p->next->V) p = p->next; //插入 NewNode->next = p->next; p->next = NewNode; } } } //使用DFS和BFS遍歷 for (int v = 0; v < Nv; v++) { int i = 0; if (!Visited[v]) { printf("{ "); DFS(v); i++; } if (i != 0) printf("}\n"); }

   //遍歷完后,需要將visited[]重新置為0
for (int v = 0; v < Nv; v++) { Visited[v] = 0; } for (int v = 0; v < Nv; v++) { int i = 0; if (!Visited[v]) { printf("{ "); BFS(v); i++; } if (i != 0) printf("}\n"); } } void DFS(int V) {
   //先訪問 visit(V); Visited[V]
= 1; for (Node v = G[V].firstEdge; v != NULL; v = v->next) { if (!Visited[v->V]) //如果沒有被訪問,就訪問 DFS(v->V); } } void BFS(int V) { Queue Q = CreateQueue(); visit(V); Visited[V] = 1; addQ(Q, V); Node p; while (!IsEmpty(Q)) { int v = DeleteQ(Q); for (p = G[v].firstEdge; p != NULL; p = p->next) { if (Visited[p->V] != 1){ visit(p->V); Visited[p->V] = 1; addQ(Q, p->V); } } } }

 

 

 

#include<stdio.h>
#include<malloc.h>
#include<math.h>

//算法思路:
//用坐標表示鱷魚的位置
//兩點距離小於跳的距離就表示兩點相連
//第一跳的距離要加上島的半徑
//存在圖中,然后dfs遍歷圖
typedef
struct Location { double x; double y; }location,Node[101]; int G[101][101]; int Ne; int Nv; //判斷是否能上岸 int flag = 0; int visited[102]; double Distance2(location a); //計算與岸上的距離 double Distance(location a, location b); //計算兩點距離 void DFS(int v); int main() { double jump; Node node; node[0].x = 0; node[0].y = 0; scanf_s("%d %lf", &Nv,&jump); double distance; double distance2; for (int i = 1; i <= Nv; i++) { scanf_s("%lf %lf", &node[i].x, &node[i].y); } int flag1 = 0; for (int i = 0; i < Nv + 1; i++) { distance = Distance(node[0], node[i]) - 15; if (distance <= jump) { G[0][i] = 1; flag1 = 1; } } if (flag1 != 1) { printf("No\n"); return 0; } //插入邊 for (int i = 1; i < Nv+1; i++) { //先算該結點是否與岸上相連 distance2= Distance2(node[i]); if (G[i][Nv+1] != 1 && distance2 <= jump) { G[i][Nv+1] = 1; } for (int j = i + 1; j < Nv+1; j++) { distance = Distance(node[i], node[j]); if (distance <= jump&&G[i][j]!=1) { G[i][j] = 1; G[j][i] = 1; } } } //判斷有沒有結點能上岸, flag1 = 0; for (int i = 0; i < Nv + 1; i++) { if (G[i][Nv + 1] == 1) { flag1 = 1; break; } } //沒有結點與岸相連 if (flag1 == 0) { printf("No\n"); return 0; } DFS(0); if (flag == 1) printf("Yes\n"); else printf("No\n"); } double Distance(location a,location b) { double distance; distance = sqrt(double(a.x - b.x)*(a.x - b.x) + double(a.y - b.y)*(a.y - b.y)); return distance; } double Distance2(location a) { double Xdistance; double Ydistance; if (a.x >= 0){ Xdistance = 50 - a.x; } else Xdistance = a.x + 50; if (a.y >= 0){ Ydistance = 50 - a.y; } else Ydistance = a.y + 50; return Xdistance < Ydistance ? Xdistance : Ydistance; } void DFS(int v) { //判斷是否與岸相連 visited[v]=1; if (v == Nv + 1) { flag = 1; return; } else { for (int i = 0; i < Nv + 2; i++) { if (G[v][i] == 1&&visited[i]!=1) { DFS(i); } } } }

 

 

 

Sample Input 1:

17 15
10 -21
10 21
-40 10
30 -50
20 40
35 10
0 -10
-25 22
40 -40
-30 30
-10 22
0 11
25 21
25 10
10 10
10 35
-30 10
 

Sample Output 1:

4
0 11
10 21
10 35
 

Sample Input 2:

4 13 -12 12 12 12 -12 -12 12 -12 
 

Sample Output 2:

0
#include<cstdio>
#include<stdlib.h>
#include<iostream>
using namespace std;

typedef struct Node *List;
struct Node
{
    int v;//在圖中的數組下標
    List next;
    double distance;
};
typedef struct GNode
{
    List FirstEdge;
    double x;
    double y;
    double distance;
}GNode,Graph[102];
double Distance2(GNode a);   //計算與岸上的距離
double Distance1(GNode a,GNode b);  //計算兩點距離
void BFS(int S,int n);
int dist[102] = {0};//存儲距離
int path[102] = { 0 }; //存儲路徑
int a[100] = { 0 }; 
Graph G;

typedef struct position
{
    double x;
    double y;
}Position[100];
int main01()
{
    
    int n, distance;
    cin >> n;
    cin >> distance;
    //原點和岸邊
    G[0].FirstEdge = NULL;
    G[0].x = 0;
    G[0].y = 0;
    G[n + 1].FirstEdge = NULL;
    dist[0] = 0;
    dist[n + 1] = -1;
    path[n + 1] = -1;
    //初始化圖,輸入坐標
    for (int i = 1; i <= n; i++)
    {
        cin >> G[i].x >> G[i].y;
        G[i].FirstEdge = NULL;
        dist[i] =path[i]= -1;
    }

    int j = 0;
    //如果第一跳直接跳上岸
    if (Distance2(G[0]) <= distance + 7.5)
    {
        cout << 1 << endl;
        return 0;
    }
    //先判斷有沒有第一跳
    for (int i = 1; i <= n; i++)
    {
        
        if (Distance1(G[0], G[i]) <= distance + 7.5)
        {
            List NewNode = (List)malloc(sizeof(struct Node));
            NewNode->v = i;
            NewNode->next = G[0].FirstEdge;
            G[i].distance = Distance1(G[0], G[i]);
            NewNode->distance = Distance1(G[0], G[i]);
            G[0].FirstEdge = NewNode;
            j++;
        }
    }
    if (j == 0)
    {
        cout << 0 << endl;
        return 0;
    }
    //將第一跳按距離排序從小到大
    for (List p = G[0].FirstEdge; p != NULL; p = p->next)
    {
        for (List p1 = p->next; p1 != NULL; p1 = p1->next)
        {
            if (p->distance > p1->distance)
            {
                int t = p->v;
                p->v = p1->v;
                p1->v = t;
                double tmp = p->distance;
                p->distance = p1->distance;
                p1->distance = tmp;
            }
        }
    }
    //插入邊
    int k = 0;
    for (int i = 1; i <= n; i++)
    {
        if (Distance2(G[i]) <= distance)
        {
            List NewNode = (List)malloc(sizeof(struct Node));
            NewNode->v = n+1;
            NewNode->next = G[i].FirstEdge;
            G[i].FirstEdge = NewNode;
            k++;
        }
        for (int j = i + 1; j <= n; j++)
        {
            if (Distance1(G[i], G[j]) <= distance)
            {
                List NewNode = (List)malloc(sizeof(struct Node));
                NewNode->v = j;
                NewNode->next = G[i].FirstEdge;
                G[i].FirstEdge = NewNode;
                NewNode = (List)malloc(sizeof(struct Node));
                NewNode->v = i;
                NewNode->next = G[j].FirstEdge;
                G[j].FirstEdge = NewNode;
            }
        }
    }
    //如果沒有與岸相連的結點
    if (k == 0)
    {
        cout << 0 << endl;
        return 0;
    }
    //遍歷
    BFS(0, n);
    int p = path[n + 1];
    int f = 1;
    Position array;
    //逆轉path輸出路徑
    while (p != 0)
    {
        array[f - 1].x = G[p].x;
        array[f - 1].y = G[p].y;
        f++;
        p = path[p];
    }
    cout << f << endl;
    for (int j = f - 2; j >= 0; j--)
    {
        cout << array[j].x << " " << array[j].y << endl;
    }
    return 0;
}
double Distance1(GNode a, GNode b)
{
    double distance;
    distance = sqrt((double)(a.x - b.x)*(a.x - b.x) + (double)(a.y - b.y)*(a.y - b.y));
    return distance;
}
double Distance2(GNode a)
{
    double Xdistance;
    double Ydistance;
    if (a.x >= 0){
        Xdistance = 50 - a.x;
    }
    else Xdistance = a.x + 50;
    if (a.y >= 0){
        Ydistance = 50 - a.y;
    }
    else Ydistance = a.y + 50;
    return Xdistance < Ydistance ? Xdistance : Ydistance;
}

typedef struct Queue
{
    int data[102];
    int front;
    int rear;
}Queue;


void BFS(int S,int n)
{
    Queue Q;
    int v;
    Q.front = Q.rear = 0;
    Q.data[Q.rear++] = S;
    while (Q.front != Q.rear)
    {
        v = Q.data[Q.front++];
        for (List p = G[v].FirstEdge; p != NULL; p = p->next)
        {
            if (dist[p->v] == -1)
            {
                if (p->v == n + 1)
                {
                    dist[p->v] = dist[v] + 1;
                    path[p->v] = v;
                    return;
                }
                else {
                    dist[p->v] = dist[v] + 1;
                    path[p->v] = v;
                    Q.data[Q.rear++] = p->v;
                }
            }
        }
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM