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 }