zoj3469 Food Delivery 区间DP

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3469

很好的区间DP

思路:

我们可以自己在本子上画一个x轴模拟一下过程,然后我们会发现对于一个区间(l,r),一旦我们访问完了l和r,那么对于整个由(l,r)组成的区间,我们一定也已经访问过了

所以我们可以定义dp[l][r][0]表示访问完区间[i,j]并留在左端点,dp[i][j][1]表示访问完区间[i,j]并留在右端点。

那么我们就比较容易的出状态转移方程:

dp[i][j][0]  可以根据dp[i+1][j][0]和dp[i+1][j][1]得到。

dp[i][j][1] 可以根据dp[i][j-1][0]和dp[i][j-1][1]得到。

具体请参考我的代码

代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 const int MAXN=1010;
 7 const int INF=0x3f3f3f3f;
 8 class person
 9 {
10    public:
11    int x;
12    int w;
13 };
14 person man[MAXN];
15 int dp[MAXN][MAXN][2];
16 bool cmp(person a,person b)
17 {
18     return a.x<b.x;
19 }
20 int sum[MAXN];
21 
22 int main()
23 {
24     int n,v,x;
25     while(scanf("%d%d%d",&n,&v,&x)==3)
26     {
27         for(int i=1;i<=n;i++)
28         {
29             scanf("%d%d",&man[i].x,&man[i].w);
30         }
31         n++;
32         man[n].x=x;
33         man[n].w=0;
34         sort(man+1,man+n+1,cmp);
35         sum[0]=0;
36         for(int i=1;i<=n;i++)
37             sum[i]=sum[i-1]+man[i].w;
38         int start;
39         for(int i=1;i<=n;i++)
40             if(man[i].x==x)
41             {
42                 start=i;
43                 break;
44             }
45         for(int i=1;i<=n;i++)
46             for(int j=1;j<=n;j++)
47                 dp[i][j][0]=dp[i][j][1]=INF;
48         dp[start][start][0]=dp[start][start][1]=0;
49         for(int i=start;i>=1;i--)
50             for(int j=start;j<=n;j++)
51             {
52                 if(i==j)continue;
53                 dp[i][j][0]=min(dp[i][j][0],dp[i+1][j][0]+(sum[i]+sum[n]-sum[j])*(man[i+1].x-man[i].x));
54                 dp[i][j][0]=min(dp[i][j][0],dp[i+1][j][1]+(sum[i]+sum[n]-sum[j])*(man[j].x-man[i].x));
55 
56                 dp[i][j][1]=min(dp[i][j][1],dp[i][j-1][0]+(sum[i-1]+sum[n]-sum[j-1])*(man[j].x-man[i].x));
57                 dp[i][j][1]=min(dp[i][j][1],dp[i][j-1][1]+(sum[i-1]+sum[n]-sum[j-1])*(man[j].x-man[j-1].x));
58             }
59        cout<<v*min(dp[1][n][0],dp[1][n][1])<<endl;//important 
60     }
61     return 0;   
62 }
View Code

 

posted on 2013-08-17 00:17  GyyZyp  阅读(203)  评论(0编辑  收藏  举报

导航