poj-1083 贪心法版本

来源:互联网 发布:冯.霍恩海姆 知乎 编辑:程序博客网 时间:2024/04/25 10:22
#include <stdio.h>
#include <stdlib.h>

struct tableMove{
    int src;
    int dst;
};

int getMax(int a, int b) {
    return a >= b ? a : b;
}

int getMin(int a, int b) {
    return a < b ? a : b;
}

void tableMoveswap(tableMove * moveA, tableMove * moveB) {
    int tmpSrc = moveA->src;
    int tmpDst = moveA->dst;
    moveA->src = moveB->src;
    moveA->dst = moveB->dst;
    moveB->src = tmpSrc;
    moveB->dst = tmpDst;
}

void sortTableMoveArrayAsDst(tableMove * tabelMoveArray, int length) {
    for (int i = 0; i < length - 1; i++) {
        bool exchanged = false;
        for (int j = 0; j <= (length - i -1) - 1; j++) {
            if (tabelMoveArray[j].dst > tabelMoveArray[j+1].dst) {
                tableMoveswap(&tabelMoveArray[j], &tabelMoveArray[j+1]);
                exchanged = true;
            }
        }
        if (exchanged == false) {
            break;
        }
    }
}

void sortTableMoveArrayAsSrc(tableMove * tabelMoveArray, int length) {
    for (int i = 0; i < length - 1; i++) {
        bool exchanged = false;
        for (int j = 0; j <= (length - i -1) - 1; j++) {
            if (tabelMoveArray[j].src > tabelMoveArray[j+1].src) {
                tableMoveswap(&tabelMoveArray[j], &tabelMoveArray[j+1]);
                exchanged = true;
            }
        }
        if (exchanged == false) {
            break;
        }
    }
}


int getMinMoveTime(tableMove * tabelMoveArray, int tabelMoveTime) {
    sortTableMoveArrayAsSrc(tabelMoveArray, tabelMoveTime);
    int moveTime = 0;
    int SUM = tabelMoveTime;
    while(1) {
        int dst = -1;
        for (int i = 0; i < tabelMoveTime; i++) {
            if (tabelMoveArray[i].dst > 0 && dst == -1) {
                dst = tabelMoveArray[i].dst;
                tabelMoveArray[i].dst = -1;
                SUM--;
            } else if (tabelMoveArray[i].dst > 0) {
                if (tabelMoveArray[i].src > dst) {
                    dst = tabelMoveArray[i].dst;
                    tabelMoveArray[i].dst = -1;
                    SUM--;
                }
            }
        }
        moveTime++;
        if (SUM == 0) {
            break;
        }
    }
    return moveTime;
}

void runOneCase() {
    int tabelMoveTime = 0;
    scanf("%d", &tabelMoveTime);
    tableMove * tabelMoveArray= (tableMove *)malloc(sizeof(tableMove) * tabelMoveTime);
    for (int i = 0; i < tabelMoveTime; i++) {    
        int src, dst = 0;
        scanf("%d %d", &src, &dst);
        if (src % 2 == 1) {
            src++;
        }
        if (dst % 2 == 1) {
            dst++;
        }
        tabelMoveArray[i].src = getMin(src, dst);
        tabelMoveArray[i].dst = getMax(src, dst);
    }
    int minMoveTime = getMinMoveTime(tabelMoveArray, tabelMoveTime);
    printf("%d\n", minMoveTime * 10);
    free(tabelMoveArray);
    tabelMoveArray = NULL;
}

int main() {
    int testCaseNum = 0;
    scanf("%d", &testCaseNum);
    for (int i = 0; i < testCaseNum; i++) {
        runOneCase();
    }

}

用贪心法的版本,

看了discuss里的另一种解答才明白为何此题能算水题(回头写一下, 也要记住)。

疑问:

       1. 按照 dst 进行排序得到的一直不对, 按照 src 就对了, 要好好看看贪心法了。

与算法导论中的贪心法实例的不同在于, 该题要求的是一个全局的最优(全部移动完所需的总次数),而实例一般求的是一次移动能移动最多的个数。

有很大的不同,上面按照src排序,再用传统贪心法,能得到答案,但是如何证明?

0 0