ECNA 2018 H Sequential Yagtzee(模拟+dp)

题意是按照顺序Yahtzee的游戏规则,已知投骰子的结果序列,求游戏的最大得分。
虽然是一看就想跑路的模拟题,然后会发现其实不难写。把计分模拟一下,然后dp出最大得分就可以了。

我们设dp[i][j]表示完成第i项规则,用了j个骰子的最大得分。那么转移时有dp[i][j+k]=max(dp[i][j+k],dp[i-1][j]+score(i,j,k)),只要求得score(i,j,k),即用j之后k个骰子(5<=k<=15),使之满足第i个规则的最大得分。
由于k比较小,可以暴力枚举换掉哪些骰子再掷一次情况的得分。枚举次数不超过2^10。

  1. /*
  2. Author: fffasttime
  3. Date: 2019/07/23 17:00
  4. */
  5. #include <bits/stdc++.h>
  6. using namespace std;
  7. typedef long long ll;
  8. #define inc(i,n) for (int i=0;i<n;i++)
  9. const int N=100010;
  10.  
  11. int seq[250], dp[14][250],step,s0;
  12. int cnt[6];
  13.  
  14. int getscore(int f[]){
  15. 	memset(cnt,0,sizeof cnt);
  16. 	inc(i,5) cnt[f[i]-1]++;
  17. 	if (step<=6) return step*cnt[step-1];
  18. 	else if (step==7){
  19. 		inc(i,6) if(cnt[i]>=3) return accumulate(f,f+5,0);
  20. 	}
  21. 	else if (step==8){
  22. 		inc(i,6) if(cnt[i]>=4) return accumulate(f,f+5,0);
  23. 	}
  24. 	else if (step==9){
  25. 		if (any_of(cnt,cnt+6,[](int x){return x==3;}) && any_of(cnt,cnt+6,[](int x){return x==2;}))
  26. 			return 25;
  27. 	}
  28. 	else if (step==10){
  29. 		inc(i,3) if (all_of(cnt+i,cnt+i+4,[](int x){return x;})) return 30;
  30. 	}
  31. 	else if (step==11){
  32. 		inc(i,2) if (all_of(cnt+i,cnt+i+5,[](int x){return x;})) return 40;
  33. 	}
  34. 	else if (step==12){
  35. 		return accumulate(f,f+5,0);
  36. 	}
  37. 	else if (step==13){
  38. 		if (any_of(cnt,cnt+6,[](int x){return x==5;})) return 50;
  39. 	}
  40. 	return 0;
  41. }
  42.  
  43. void dfs(int s, int f[], int d){
  44. 	dp[step][s]=max(dp[step][s],getscore(f)+dp[step-1][s0]);
  45. 	if (d==2) return;
  46. 	int cur[5];
  47. 	for (int i=1;i<32;i++){
  48. 		int us=s;
  49. 		copy(f,f+5,cur);
  50. 		for (int j=0;j<5;j++) if(i>>j&1)
  51. 			cur[j]=seq[us++];
  52. 		dfs(us,cur,d+1);
  53. 	}
  54. }
  55.  
  56. void solve(int s){
  57. 	int f[5];
  58. 	for (int i=0;i<5;i++) f[i]=seq[s+i];
  59. 	dfs(s+5,f,0);
  60. }
  61.  
  62. int main(){
  63. 	fill(seq,seq+220,1);
  64. 	int n; cin>>n;
  65. 	inc(i,n) scanf("%d",seq+i);
  66. 	for (step=1;step<=13;step++){
  67. 		for (int j=(step-1)*5;(j<=(step-1)*15) && j<=n;j++){
  68. 			s0=j;
  69. 			solve(j);
  70. 		}
  71. 	}
  72. 	cout<<*max_element(dp[13],dp[13]+n+1)<<'\n';
  73. 	return 0;
  74. }

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注