使用C语言动态规划完成: 游戏规则是这样的:如上图所示所有的小球都布局在一行上,每个小球都有自己的颜色,连续摆放的同颜色小球构成一个小球片段,上图中共有14个小球片段,每个小球片段分别有:5、2、1、2、1、1、1、2、1、1、1、1、1、1个小球片段,玩家每次点击一个小球,则该小球所在的小球片段就会消失。若消失的小球片段中共有m个小球,则玩家获得m*m个积分。请问:给定游戏开始时的状态,玩家可获得的最高积分是多少?输入格式: 第一行是一个整数n(1<=n<=15),表示共有n组测试数据。 接下来每组测试数据共包括两行: (1)第1行是一个整数k(1<=k<=200),表示共有k个小球; (2)第2行包含k个正整数,表示每个小球的颜色这些整数的取值范围是[1,n]。 输出格式: 对每组测试数据,输出玩家可以获得的最高积分,每组数据的输出单独占一行
时间: 2024-03-22 15:38:40 浏览: 86
以下是C语言动态规划代码实现:
```c
#include <stdio.h>
#include <string.h>
#define MAXK 200
#define MAXS (1 << MAXK)
int k, n;
int ball[MAXK + 1];
int dp[MAXS];
int max(int a, int b) {
return a > b ? a : b;
}
int main() {
int T;
scanf("%d", &T);
while (T--) {
scanf("%d", &k);
memset(dp, 0, sizeof(dp));
for (int i = 0; i < k; i++) {
scanf("%d", &ball[i]);
}
// 状态压缩动态规划
for (int S = 1; S < (1 << k); S++) {
int sum = 0, color = -1;
for (int i = 0; i < k; i++) {
if ((S & (1 << i)) && ball[i] != color) {
// 枚举所有可能的子集
int T = S ^ (1 << i);
for (int j = 0; j < i; j++) {
if ((T & (1 << j)) && ball[j] == ball[i]) {
T ^= (1 << j);
}
}
// 计算得分并更新状态
int m = 0;
for (int j = 0; j < k; j++) {
if ((T & (1 << j)) && ball[j] == ball[i]) {
m += ball[j];
}
}
dp[S] = max(dp[S], dp[T] + m * m);
color = ball[i];
}
}
}
printf("%d\n", dp[(1 << k) - 1]);
}
return 0;
}
```
其中,变量S表示当前小球片段的状态,变量T表示S的一个子集,且T中所有小球片段的颜色都相同。在计算T时,需要枚举所有可能的子集,并判断其中的小球片段是否颜色相同。在计算得分时,需要遍历所有在T中的小球,并计算它们的总数m。最终的答案即为dp[(1<<k)-1],表示所有小球片段都被消除时所能获得的最高积分。
阅读全文