POJ 1178 Floyd

来源:互联网 发布:北京六道口 知乎 编辑:程序博客网 时间:2024/04/28 21:50

先给一个我最先写的一个代码吧。总体思路是这样的,对于每个输入的点,都进行一次广搜,打出到达其他点的最短路径(这个效率相比于floyd太低了)再加在ans数组当中,最后搜索出最小值,并输出。虽然这个代码能过很多数据,但是 Discuss 里A1A2A3H2H5H6H7H8C1C2C5C6C7E2E3E4E5E6E7E8 就过不了。

至于原因还望大牛们给予指点。我预测可能是广搜有问题,我原以为,用广搜打出的路径表一定就严格递增的,所以我就这么写了,不过后来还是有问题,望各位指点啊。

我的错误代码如下:

#include <stdio.h>#include <iostream>#include <string.h>#include <queue>using namespace std;#define LEN 8#define MIN(a,b) (a<b?a:b)int ans[LEN][LEN];int king[LEN][LEN];int knight[LEN][LEN];int flag[LEN][LEN];int count = 0;int point[8][2] = {{-1, -2},{-1, 2},{1, -2},{1, 2},{-2, -1},{-2, 1},{2, -1},{2, 1}};/*void find(int x, int y, int n) {if(x < 0 || x >= LEN || y < 0 || y >= LEN) {return;}if(count > 128) return;count++;knight[x][y] = MIN(knight[x][y], n+1);find(x-1, y-2, knight[x][y]);find(x-1, y+2, knight[x][y]);find(x+1, y-2, knight[x][y]);find(x+1, y+2, knight[x][y]);find(x-2, y-1, knight[x][y]);find(x-2, y+1, knight[x][y]);find(x+2, y-1, knight[x][y]);find(x+2, y+1, knight[x][y]);}*/int _abs(int a) {return a < 0 ? (-a) : (a);}void find(int sx, int sy) {queue<int> queue;while(!queue.empty()) {queue.pop();}queue.push(sx);queue.push(sy);queue.push(0);flag[sx][sy] = 1;while(!queue.empty()) {int x = queue.front();queue.pop();int y = queue.front();queue.pop();int n = queue.front();queue.pop();for(int i = 0; i < 8; i++) {int xx = x+point[i][0];int yy = y+point[i][1];if(xx < 0 || xx >= LEN || yy < 0 || yy >= LEN) {continue;}if(flag[xx][yy]) {continue;}flag[xx][yy] = 1;knight[xx][yy] = n+1;queue.push(xx);queue.push(yy);queue.push(n+1);}}}void init() {for(int i = 0; i < LEN; i++) {for(int j = 0; j < LEN; j++) {knight[i][j] = 99999;}}knight[0][0] = 0;}void pr() {for(int i = 0; i < LEN; i++) {for(int j = 0; j < LEN; j++) {cout<< ans[i][j]<< " ";}cout<< endl;}cout<< endl;}void pri() {for(int i = 0; i < LEN; i++) {for(int j = 0; j < LEN; j++) {cout<< knight[i][j]<< " ";}cout<< endl;}cout<< endl;}int main() {char str[10000];int index, i, j, k;memset(king, 0, sizeof(king));memset(flag, 0, sizeof(flag));init();king[0][0] = 0;for(i = 1; i < LEN; i++) {king[0][i] = king[0][i-1] + 1;king[i][0] = king[i-1][0] + 1;}for(i = 1; i < LEN; i++) {for(j = 1; j < LEN; j++) {king[i][j] = MIN(king[i][j-1], MIN(king[i-1][j], king[i-1][j-1])) + 1;}}while(gets(str)) {memset(ans, 0, sizeof(ans));int k1 = str[0]-'A';int k2 = str[1]-'0'-1;for(i = 0; i < LEN; i++) {for(j = 0; j < LEN; j++) {ans[i][j] += _abs(king[i][j]-king[k1][k2]);}}//pr();for(index = 2; str[index] != '\0'; index += 2) {int t1 = str[index]-'A';int t2 = str[index+1] - '0' - 1;memset(knight, 0, sizeof(knight));memset(flag, 0, sizeof(flag));find(t1, t2);//pri();for(i = 0; i < LEN; i++) {for(j = 0; j < LEN; j++) {ans[i][j] += _abs(knight[i][j]-knight[t1][t2]);}}//pr();}int min = 99999;for(i = 0; i < LEN; i++) {for(j = 0; j < LEN; j++) {min = MIN(min, ans[i][j]);}}printf("%d\n", min);memset(str, 0, sizeof(str));}return 0;}


正确的 DP + floyd 解法, 其实最主要的就是把原来的那个 map 转换成为一个新的二维数组。

A1A2A3H2H5H6H7H8C1C2C5C6C7E2E3E4E5E6E7E8#include <cstdio>#include <iostream>#include <cstring>#include <string>using namespace std;#define MAX 8const int INF = (1<<20);int dirKing[8][2] = {{1,0},{-1,0},{0,1},{0,-1},{1,1},{-1,-1},{1,-1},{-1,1}};int dirKnight[8][2] = {{-2,-1},{-2,1},{2,-1},{2,1},{-1,-2},{1,-2},{-1,2},{1,2}};char str[MAX*MAX*2+5];int king[MAX*MAX][MAX*MAX], knight[MAX*MAX][MAX*MAX];int step[MAX*MAX], num;inline int min(int a,int b){    return a < b ? a : b;}void init(){    for(int i = 0; i < MAX*MAX; ++i)        for(int j = 0; j < MAX*MAX; ++j)            king[i][j] = knight[i][j] = (i == j ? 0 : INF);    for(int i = 0; i < MAX*MAX; ++i)    {        int x = i/8;        int y = i%8;        for(int j = 0; j < 8; ++j)        {            int xx = x+dirKing[j][0];            int yy = y+dirKing[j][1];            if(xx >= 0 && xx < MAX && yy >= 0 && yy < MAX)                king[i][8*xx+yy] = 1;        }                for(int j = 0; j < 8; ++j)        {            int xx = x+dirKnight[j][0];            int yy = y+dirKnight[j][1];            if(xx >= 0 && xx < MAX && yy >= 0 && yy < MAX)                knight[i][8*xx+yy] = 1;        }    }}void floyd(int a[][MAX*MAX]){    for(int k = 0; k < MAX*MAX; ++k)    {        for(int i = 0; i < MAX*MAX; ++i)        {            for(int j = 0; j < MAX*MAX; ++j)            {                if(a[i][j] > a[i][k]+a[k][j])                    a[i][j] = a[i][k]+a[k][j];            }        }    }}int main(){//    freopen("input.txt","r",stdin);    init();    floyd(king);    floyd(knight);        while(scanf("%s",str) != EOF)    {        int start = (str[0]-'A') + (str[1]-'1')*8;        int num = (strlen(str)-2)/2;        if(num == 0)        {            printf("0\n");            continue;        }                for(int i = 0, j = 2; i < num; ++i, j+=2)            step[i] = (str[j]-'A') + (str[j+1]-'1')*8;        int result = INF;        int t1, t2;        int sum;        for(int i = 0; i < MAX*MAX; ++i)        {            sum = 0;            for(int k = 0; k < num; ++k)                sum += knight[ step[k] ][i];            for(int j = 0; j < MAX*MAX; ++j)            {                t1 = king[start][j];                t2 = INF;                for(int kk = 0; kk < num; ++kk)                {                    t2 = min(t2,knight[ step[kk] ][j] + knight[j][i] - knight[ step[kk] ][i]);                 }                result = min(result,sum+t1+t2);            }        }        printf("%d\n",result);    }    return 0;}



原创粉丝点击