Luogu P1541 [NOIP2010 提高组] 乌龟棋题解
有两种方法,代码注释都很详细了直接上代码
一:记忆化搜索
1 #include<bits/stdc++.h> 2 using namespace std; 3 int t[15]; 4 int n, m; 5 int a[400]; 6 int mp[45][45][45][45];//mp[i][j][k][l]表示1号用i张,2号用j张,3号用k张,4号用l张的情况下,最多能拿多少分 7 int dfs(int step, int w)//step表示处理了几张卡片 w是现在的位置 8 { 9 if (mp[t[1]][t[2]][t[3]][t[4]])//如果已经有值 10 return mp[t[1]][t[2]][t[3]][t[4]];//直接返回 11 if (step == m)//都决定完了 12 return a[w];//返回此位置的值 13 int cnt = 0; 14 for (int i = 1;i <= 4; i++) 15 if (t[i] != 0) 16 { 17 t[i]--; 18 cnt = max(dfs(step + 1, w + i), cnt);//找后面所有情况中的最大值 19 t[i]++; 20 } 21 return mp[t[1]][t[2]][t[3]][t[4]] = cnt + a[w];//加上此位置的值为该状态下的最大值 22 } 23 int main() 24 { 25 scanf ("%d%d", &n, &m); 26 for (int i = 0;i < n; i++) 27 scanf ("%d", a + i); 28 for (int i = 0, x;i < m; i++) 29 { 30 scanf ("%d", &x); 31 t[x]++; 32 } 33 dfs(0, 0); 34 printf ("%d", mp[t[1]][t[2]][t[3]][t[4]]); 35 return 0; 36 }
二:用神奇的四重循环
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N = 45; 4 int n, m; 5 int f[N][N][N][N];//f[i][j][k][l]表示1号用i张,2号用j张,3号用k张,4号用l张时最多能拿多少分 6 int t[10]; 7 int a[355]; 8 int main() 9 { 10 scanf ("%d%d", &n, &m); 11 for (int i = 0;i < n; i++) 12 scanf ("%d", a + i); 13 for (int i = 0, x;i < m; i++) 14 { 15 scanf ("%d", &x); 16 t[x]++; 17 } 18 f[0][0][0][0] = a[0];//初始化 19 for (int t1 = 0;t1 <= t[1]; t1++)//循环1的张数 20 for (int t2 = 0;t2 <= t[2]; t2++)//循环2的张数 21 for (int t3 = 0;t3 <= t[3]; t3++)//循环3的张数 22 for (int t4 = 0;t4 <= t[4]; t4++)//循环4的张数 23 { 24 int tt = t1 + t2 * 2 + t3 * 3 + t4 * 4;//算出现在的位置 (我是从0开始的) 25 if (t1)//如果1的张数不唯一,就可以求出去1张1,并求最大值 26 f[t1][t2][t3][t4] = max(f[t1][t2][t3][t4], f[t1 - 1][t2][t3][t4] + a[tt]); 27 if (t2)//同上 28 f[t1][t2][t3][t4] = max(f[t1][t2][t3][t4], f[t1][t2 - 1][t3][t4] + a[tt]); 29 if (t3)//同上 30 f[t1][t2][t3][t4] = max(f[t1][t2][t3][t4], f[t1][t2][t3 - 1][t4] + a[tt]); 31 if (t4)//同上 32 f[t1][t2][t3][t4] = max(f[t1][t2][t3][t4], f[t1][t2][t3][t4 - 1] + a[tt]); 33 } 34 //结果在用 1号用t[1]张,2号用t[2]张,3号用t[3]张,4号用t[4]张里 35 //即在 f[t[1]][t[2]][t[3]][t[4]]里 36 printf ("%d", f[t[1]][t[2]][t[3]][t[4]]); 37 return 0; 38 }
完结撒花

浙公网安备 33010602011771号