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 }

完结撒花

posted @ 2022-01-08 13:10  睡不醒的凪  阅读(20)  评论(0)    收藏  举报