HNU 暑假练习赛-0902-Sleeping at Work 解题报告

这道题很容易能看出来要用动态规划,但是背包确实不是很好想,用数组v[i][j]表示到i分钟,已经连续睡了j分钟所获得的价值,这样对于一个特定的点i所有的j就变成了矛盾的了,状态转移方程就很好

写了

View Code
 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #define N 505
 5 #define M 55
 6 #define R 55
 7 using namespace std;
 8 int dp[N][M],v[N][R];
 9 int val[N];
10 int max(int a,int b)
11 {
12     return a>b?a:b;
13 }
14 int min(int a,int b)
15 {
16     return a<b?a:b;
17 }
18 int add(int i,int j)
19 {
20     int sum=0;
21     int k;
22     for(k=i;i-k<=j;k--)
23     sum+=((j-(i-k))*val[k]);
24     return sum;
25 }
26 int main()
27 {
28     int n,i,j,k,m,r,l;
29     int t;
30     scanf("%d",&t);
31     while(t--)
32     {
33         scanf("%d%d%d",&n,&m,&r);
34         memset(dp,0,sizeof(dp));
35         for(i=1;i<=n;i++)
36         scanf("%d",&val[i]);
37         if((n-n/(r+1))<m)
38         {
39             printf("impossible\n");
40             continue;
41         }
42         for(i=1;i<=n;i++)
43         for(j=0;j<=i&&j<=r;j++)
44         v[i][j]=add(i,j);
45         for(i=1;i<=n;i++)
46         {
47             for(j=min(m,i);j>=0;j--)
48             {
49                 int temp=0;
50                 for(k=min(r,j);k>=0;k--)
51                 {
52                     if(i==k&&j==k)
53                     temp=max(temp,v[i][k]);
54                     else if(i-k-1>=j-k)//注意这里是为了保证状态的合法性
55                     temp=max(temp,dp[i-k-1][j-k]+v[i][k]);
56                }
57                dp[i][j]=temp;
58 
59             }
60         }
61         int amax=0;
62         for(i=1;i<=n;i++)
63         if(amax<dp[i][m])
64         amax=dp[i][m];
65         printf("%d\n",amax);
66     }
67     return 0;
68 }

另一种DP解法:三维的D

P解法,dp[i][j][k]表示到第i个时间点,总共睡了j分钟,连续睡了k分钟的价值最大值,那么如果在第i个点睡的话,那么就直接等于DP[i-1][j-1][k-1]+k*val[i](保证状态可达),否则,如果在i分钟不睡的话,dp[i][j][0]=max(dp[i-1][j][k],k>=0&&k<=r)

 

View Code
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 int max(int a,int b)
 6 {
 7 return a>b?a:b;
 8 }
 9 int dp[505][55][55];
10 int a[505];
11 int main()
12 {
13     int t,i,j,k,n,m,r;
14     scanf("%d",&t);
15     while(t--)
16     {
17         scanf("%d%d%d",&n,&m,&r);
18         a[0]=0;
19         for(i=1;i<=n;i++)
20             scanf("%d",&a[i]);
21         memset(dp,-1,sizeof(dp));
22         for(i=0;i<=n;i++)
23             dp[i][0][0]=0;
24         for(i=1;i<=n;i++)
25             for(j=1;j<=m&&j<=i;j++)
26             {
27                 for(k=1;k<=r&&k<=j;k++)
28                 {
29                     if(dp[i-1][j-1][k-1]==-1)
30                         dp[i][j][k]=-1;
31                     else 
32                         dp[i][j][k]=dp[i-1][j-1][k-1]+k*a[i];
33                     if(dp[i-1][j][k]>dp[i][j][0])
34                         dp[i][j][0]=dp[i-1][j][k];
35                 }
36                 dp[i][j][0]=max(dp[i][j][0],dp[i-1][j][0]);
37             }
38         int res=-1;
39         for(k=0;k<=r;k++)
40             res=max(res,dp[n][m][k]);
41         if(res==-1)
42             printf("impossible\n");
43         else printf("%d\n",res);
44     }
45     return 0;
46 }
posted @ 2012-09-02 15:07  zhenhai  阅读(181)  评论(0编辑  收藏  举报