Lightoj 1057 DP

一开始还以为是BFS+DP,最后发现距离是可以直接算的。。。。

然后有一点要注意的是 如果没有g直接输出0......

我用的是状态压缩DP

AC代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;

#define MAX 0x3f3f3f3f

typedef struct{
	int x, y;
}Point;

char maps[21][21];
int M, N;
Point point[20];
int point_number;
int distances[20][20];
int dp[1<<16][17];

int calculate_distance( Point p1, Point p2 ){
	int a = abs( p1.x - p2.x );
	int b = abs( p1.y - p2.y );
	return a > b ? a : b;
}

int main(){
	int T, Case = 1;

	cin >> T;
	while( T-- ){
		cin >> M >> N;
		point_number = 1;
		
		for( int i = 0; i < M; i++ ){
			cin >> maps[i];
			for( int j = 0; j < N; j++ ){
				if( maps[i][j] == 'x' ){
					point[0].x = i;
					point[0].y = j;
				}else if( maps[i][j] == 'g' ){
					point[point_number].x = i;
					point[point_number++].y = j;
				}
			}
		}
		point_number--;

		if( point_number == 0 ){// 如果没有g  则直接输出0 注意!
			cout << "Case " << Case++ << ": " << 0 << endl;
			continue;
		}

		for( int i = 0; i <= point_number; i++ ){
			for( int j = i + 1; j <= point_number; j++ ){
				distances[i][j] = distances[j][i] = calculate_distance( point[i], point[j] );
			}
		}

		memset( dp, -1, sizeof( dp ) );
		for( int i = 1; i <= point_number; i++ ){
			dp[1<<(i-1)][i] = distances[0][i];
		}
		for( int i = 1; i <= ( 1 << point_number ) - 1; i++ ){
			for( int j = 1; j <= point_number; j++ ){
				if( ( i & ( 1 << ( j - 1 ) ) ) == 0 ){
					continue;
				}
				for( int k = 1; k <= point_number; k++ ){
					if( i & ( 1 << ( k - 1 ) ) ){
						continue;
					}
					if( dp[i|(1<<(k-1))][k] == -1 || dp[i|(1<<(k-1))][k] > dp[i][j] + distances[j][k] ){
						dp[i|(1<<(k-1))][k] = dp[i][j] + distances[j][k];
					}
				}
			}
		}
		int ans = MAX;
		for( int i = 1; i <= point_number; i++ ){
			ans = min( ans, dp[(1<<point_number)-1][i] + distances[i][0] );
		}
		cout << "Case " << Case++ << ": " << ans << endl;
	}
	return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值