赛后总结:第一次距离金这么近,而且这道题几乎同类型的题,某acw网站算法基础课的 最短Hamilton路径,我还做过,但是当时没有想到两者一些相同的性质,还是练的少,明年省赛继续努力吧。
光棍节即将来临,小辣参加了某资本家的某游戏
即四根光棍在如图场景进行游戏,每个格子有一个数值 你可以掷若干次骰子,每次随机掷出 1 ~ 6 之间的整数值,加入糖果库存
如果某次掷骰子后你的糖果库存大于某个格子的数值,且这个格子与你占领的格子相邻,那么你可以选择占领这个格子,占领后库存清 0
我们称两个格子相邻当且仅当有一条边重合 默认一开始你位于左下方(即图中显示“我方”的位置),也就是说只有左下方的格子与你相邻
小辣用二十年单身换取了 n 次掷骰子的机会,你能告诉他最好情况下最多能占领几个格子吗
输入
第一行一个整数 T, 表示数据组数。对于每组数据:
第一行 17 个正整数,依次表示图中从左到右从上到下17个格子的数值,前四个表示第一行四个格子,第五到七表示第二行三个,以此类推。
第二行 1 个非负整数 n,表示掷骰子的次数
1≤T≤20, 保证所有数据 ≤109
输出
对于每组样例输出一行一个整数,表示最多能占领的格子数量
样例输入 Copy
2
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
10
10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
100
样例输出 Copy
10
17
简单解题代码+思路注释
#include <bits/stdc++.h>
using namespace std;
int t,ar[20],sum,ans,cnt;
bool st[6][6]; /// 建图需要的数组
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; /// 搜索上下左右四个方向
void init(int x) /// 建图
{
if(x==1) st[5][1] = true;
else if(x==2) st[5][2] = true;
else if(x==3) st[5][4] = true;
else if(x==4) st[5][5] = true;
else if(x==5) st[4][2] = true;
else if(x==6) st[4][3] = true;
else if(x==7) st[4][4] = true;
else if(x==8) st[3][2] = true;
else if(x==9) st[3][3] = true;
else if(x==10) st[3][4] = true;
else if(x==11) st[2][2] = true;
else if(x==12) st[2][3] = true;
else if(x==13) st[2][4] = true;
else if(x==14) st[1][1] = true;
else if(x==15) st[1][2] = true;
else if(x==16) st[1][4] = true;
else if(x==17) st[1][5] = true;
}
void dfs(int x,int y) /// 只搜一遍获取最大连通块数量
{
st[x][y] = false; cnt++;
for(int i=0; i<4; i++)
{
int dx_1 = x+dx[i],dy_1 = y+dy[i];
if(dx_1<1||dx_1>5||dy_1<1||dy_1>5||!st[dx_1][dy_1]) continue;
dfs(dx_1,dy_1);
}
}
int main()
{
cin>>t;
while(t--)
{
ans = 0; /// 记录能达到的最多的点
for(int i=1; i<=17; i++) cin>>ar[i]; /// 存下每个方格需要的糖果数量
cin>>sum; /// 筛子个数
for(int i=0; i< 1<<17; i++) /// 把所有情况不重复遍历一遍
{
memset(st, 0, sizeof st); /// 每次使用方法都要把数组重置一下
int res = 0,sum1=0; /// sum1记录每一种方法所使用的糖果数
for(int j=0; j<17; j++) /// 一共17个点所以要进行
{
if(i>>j&1)
{
res++;
init(j+1);
if(ar[j+1]%6!=0) sum1+=(ar[j+1]/6+1); ///每次使用筛子的判定
else sum1+=(ar[j+1]/6);
}
}
if(sum<sum1) continue;
cnt = 0;
if(!st[1][1]) continue; /// 起始点不存在的情况
dfs(1,1); /// 判断选中的几个点能否连通成一个连通块
if(res == cnt) ans = max(ans,res);
}
cout<<ans<<"\n";
}
return 0;
}