zoukankan      html  css  js  c++  java
  • HNU 暑假练习赛0902Sleeping 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 }
  • 相关阅读:
    day09_request&response学习笔记
    为什么浏览器User-agent(浏览器类型)总是有Mozilla字样?
    无效类字符串:ProgID: Excel.Application
    django2.0升级日记
    Kali Linux信息收集工具
    Kali Linux 工具使用中文说明书
    人手一份核武器
    五大常用算法【转发】
    ACCA AI来袭会议笔记
    2017 Gartner数据科学魔力象限出炉,16位上榜公司花落谁家?
  • 原文地址:https://www.cnblogs.com/caozhenhai/p/2667552.html
Copyright © 2011-2022 走看看