其他分享
首页 > 其他分享> > Pokemon Go Go (状压dp)

Pokemon Go Go (状压dp)

作者:互联网

//捕捉宝可梦
//考虑状压dp,一维是宝可梦的捕捉状态,二维保存当前捕捉的宝可梦编号
const int inf = 0x3f3f3f3f;
int n, cnt;
int dp[1 << 20][22];//dp[sta][point]
unordered_map<string, int> mp;
struct point {
	int x, y;
	int type;
};
point a[25];
string s;

int get_cal(point i, point j) {
	return abs(i.x - j.x) + abs(i.y - j.y);
}

int main() {
	ios::sync_with_stdio(0);

	while (cin >> n) {
		for (int i = 0; i < n; ++i) {
			cin >> a[i].x >> a[i].y;
			cin >> s;
			if (!mp.count(s))	mp[s] = cnt++;
			a[i].type = mp[s];
		}

		memset(dp, inf, sizeof dp);

		for (int i = 0; i < n; ++i) {//初始化:原点到每种宝可梦的最短距离
			dp[(1 << a[i].type)][i] = min(dp[(1 << a[i].type)][i], get_cal(a[n + 3], a[i]));//a[n+3]可看作原点
		}

		int limit = (1 << cnt);
		for (int i = 0; i < limit; ++i) {//枚举状态
			if ((i == (i & -i)))	continue;//已经初始化,跳过
			for (int j = 0; j < n; ++j) {//当前选择的点
				if (!(i & (1 << a[j].type)))	continue;
				int last = i - (1 << a[j].type);//前一次的状态
				for (int k = 0; k < n; ++k) {//前一次选择的点
					if (last & (1 << a[k].type))	dp[i][j] = min(dp[i][j], dp[last][k] + get_cal(a[k], a[j]));
				}
			}
		}

		int ans = inf;
		for (int i = 0; i < n; ++i)
			ans = min(ans, dp[limit - 1][i] + get_cal(a[n + 3], a[i]));//a[n+3]未初始化,为(0,0)
		cout << ans << endl;
	}
	return 0;
}

标签:point,int,状压,宝可梦,++,mp,Go,Pokemon,dp
来源: https://www.cnblogs.com/wanshe-li/p/13757296.html