http://acm.zzuli.edu.cn/problem.php?id=2827

思路

一共17个格子, 每次只能走相邻的, 求能走的最长路径。

解法1:建图 从起点开始标号, 当A与B相邻时, 从A到B连一条权值为B的边, 从B到A连一条权值为A的边。

然后直接DFS开搜, 用st来保存当前路径上走过的点。 假设每次筛子都投6, 通过处理, 把每个点的权值从糖果数改为最少扔筛子数即可, (w[i] + 5) / 6

解法2:状态压缩 一共17个格子, 故可以用二进制来表示每个格子是否选中。 2^17 == 131072 不会超时。

对于每个位置用DFS来搜索判断该状态是否不成立。

代码

解法2

#include <iostream>
#include <cstring>
#include <algorithm>
#include <iomanip>
#define int long long
using namespace std;
const int N = 20, mod = 1e9 + 7;
int n;
int a[18];
int w[N];
int arrive, cnt;
int x[] = {1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5};
int y[] = {1, 2, 4, 5, 2, 3, 4, 2, 3, 4, 2, 3, 4, 1, 2, 4, 5};
int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
int mp[10][10];
 
bool dfs(int x, int y, int state)
{
	if(arrive == state && cnt <= n) return true;
	int id = mp[x][y];
 
	if(id == -1 || !(state >> id & 1) || (arrive >> id & 1)) return false;
 
	arrive |= 1 << id;
	cnt += w[id];
 
	for(int i = 0; i < 4; i++)
	{
		if(dfs(x + dx[i], y + dy[i], state))
			return true;
	}
	return false;
}
 
main()
{
	memset(mp, -1, sizeof mp);
	for (int i = 0; i < 17; i++)
		mp[x[i]][y[i]] = i;
	int T;
	cin >> T;
	while (T--)
	{
		for (int i = 0; i < 17; i++)
			cin >> w[i], w[i] = (w[i] + 5) / 6;
		cin >> n;
		int res = 0;
		for (int i = 0; i < 1 << 17; i++)
		{
			if (i >> 13 & 1 == 0)
				continue;
			arrive = 0, cnt = 0;
			if (dfs(x[13], y[13], i))
				res = max(res, __builtin_popcount(i));
		}
		cout << res << endl;
	}
	return 0;
}