hdu4283 You Are the One 区间DP

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4283

自己想了很久还是不会,参考了别人的思路才写的,区间DP还是很弱,继续努力!!

思路:

转载:

题解:想dp[i][j]表示[i ,j]内的unhappiness最小值,枚举k(i<=k<j),有两种情况需要讨论:
          1 如果[i , k]区间内的人全部在[k+1, j]区间内的人之前出列,且已经全部不在栈中,即[i , j]区间可以分为[i , k] , [k+1 ,j]两个完全相同的子问题,
             即dp[i][j] =MIN(dp[i][j] , dp[i][k] + dp[k+1][j] + (sum[j] – sum[i]) * (k – i +1));
          2 如果[i , k]区间内的人全部在[k+1 , j]区间内的人之后出列,即[i , k]区间内的人全部需要进栈,所以出来的顺序是逆序的,需O(n2)预处理出against_order[i][j]
             表示[i , j]区间人逆序出来的unhappiness值,即dp[i][j] = MIN(dp[i][j] , dp[k+1][j] + against_order[i][k] + (sum[k]– sum[i-1]) * (j - k));

我用了记忆化搜索和迭代两种方式实现,主要是为了加深自己的理解和记忆

记忆化搜索代码 :

 1 #include<iostream>
 2 #include<cstdlib>
 3 #include<cstdio>
 4 #include<cstring>
 5 using namespace  std;
 6 #define  INF 1000010111
 7 int n;
 8 int a[110];
 9 int dp[110][110];
10 int sum[110];
11 int order[110][110];
12 void Make_order()
13 {
14         memset(order,0,sizeof(order));
15         for(int j=1;j<=n;j++)
16                 for(int i=j-1;i>=1;i--)
17                         order[i][j]=order[i+1][j]+a[i]*(j-i);
18 
19 }
20 int dfs(int i,int j)
21 {
22         if(dp[i][j]<INF) return dp[i][j];
23         if(i==j) return dp[i][j]=0;
24         for(int k=i;k<j;k++)
25                 dp[i][j]=min(dp[i][j],min(dfs(i,k)+dfs(k+1,j)+(sum[j]-sum[k])*(k-i+1),dp[k+1][j]+order[i][k]+(sum[k]-sum[i-1])*(j-k)));
26                 return dp[i][j];
27 }
28 int main()
29 {
30         int t;
31         scanf("%d",&t);
32         int tol=1;
33         while(t--)
34         {
35                 sum[0]=0;
36                 scanf("%d",&n);
37                 for(int i=1;i<=n;i++)
38                    {
39                            scanf("%d",&a[i]);
40                            sum[i]=sum[i-1]+a[i];
41                    }
42                 Make_order();
43                   for(int i=0;i<110;i++)
44                       for(int j=0;j<110;j++)
45                               dp[i][j]=INF;
46                   cout<<"Case #"<<tol++<<": "<<dfs(1,n)<<endl;
47         }
48 
49 
50 }

迭代代码:

 1 #include<iostream>
 2 #include<cstdlib>
 3 #include<cstdio>
 4 #include<cstring>
 5 using namespace std;
 6 #define INF 100001000
 7 int dp[110][110];
 8 int a[110];
 9 int sum[110];
10 int order[110][110];
11 int n;
12 void init()
13 {
14         scanf("%d",&n);
15        sum[0]=0;
16        for(int i=1;i<=n;i++)
17        {
18                scanf("%d",&a[i]);
19                sum[i]=sum[i-1]+a[i];
20        }
21        for(int i=1;i<110;i++)
22            for(int j=i;j<110;j++)
23                    if(i==j) dp[i][j]=0;
24                    else dp[i][j]=INF;
25        memset(order,0,sizeof(order));
26        for(int j=1;j<=n;j++)
27           for(int i=j-1;i>=1;i--)
28                   order[i][j]=order[i+1][j]+a[i]*(j-i);
29 }
30 
31 int main()
32 {
33         int t;
34         int tol=1;
35         scanf("%d",&t);
36         while(t--)
37         {
38           init();
39           for(int j=1;j<=n;j++)
40              for(int i=j-1;i>=1;i--)
41                {
42                   for(int k=i;k<j;k++)
43                     dp[i][j]=min(dp[i][j],min(dp[i][k]+dp[k+1][j]+(sum[j]-sum[k])*(k-i+1),dp[k+1][j]+order[i][k]+(sum[k]-sum[i-1])*(j-k)));
44                }
45                cout<<"Case #"<<tol++<<": "<<dp[1][n]<<endl;
46         }
47         return 0;
48      
49 }

 

posted on 2013-08-14 21:54  GyyZyp  阅读(233)  评论(0编辑  收藏  举报

导航