HDU 4283 You Are the One(区间DP)

题目链接

这个我是用记忆化搜索写的。比赛的时候卡死在这里,以为是个简单的二维DP,思维被局限了,以前也没怎么做过区间DP,没做出,不过还是觉得理解了状态状态转移,代码什么的都是很短。dp[x][y][z]的意义是在x-y这一段上,前面已经有z-1个人唱歌了,所取得的最小值,这个DFS的写的有点感觉像是树形DP,递推能力太搓了。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <cmath>
 6 #include <map>
 7 #include <queue>
 8 #include <set>
 9 #include <vector>
10 #define INF 1
11 #define LL __int64
12 using namespace std;
13 int dp[101][101][101];
14 int p[101];
15 int dfs(int x,int y,int z)
16 {
17     int i,ans;
18     if(x > y)//注意这种情况
19     return 0;
20     if(x == y)
21     {
22         dp[x][y][z] = p[x]*z;
23         return dp[x][y][z];
24     }
25     if(dp[x][y][z] != INF)
26     return dp[x][y][z];
27     ans = z*p[x] + dfs(x+1,y,z+1);//初始假设第x个人在第z位置唱歌
28     for(i = x+1;i <= y;i ++)
29     {
30         ans = min(ans,dfs(x+1,i,z)+dfs(i+1,y,z+i-x+1)+p[x]*(z+i-x));//枚举第x个人在z+i-x位置唱歌,则区间被分成了两块。
31     }
32     dp[x][y][z] = ans;
33     return ans;
34 }
35 int main()
36 {
37     int t,i,j,k,n,num = 0;
38     scanf("%d",&t);
39     while(t--)
40     {
41         scanf("%d",&n);
42         for(i = 1;i <= n;i ++)
43         scanf("%d",&p[i]);
44         for(i = 0;i <= n;i ++)//求最小,初始化为很大的数
45         {
46             for(j = 0;j <= n;j ++)
47             {
48                 for(k = 0;k <= n;k ++)
49                 dp[i][j][k] = INF;
50             }
51         }
52         printf("Case #%d: ",++num);
53         printf("%d\n",dfs(1,n,0));
54     }
55     return 0;
56 }

 

posted @ 2012-09-25 20:10  Naix_x  阅读(148)  评论(0编辑  收藏  举报