码迷,mamicode.com
首页 > 其他好文 > 详细

10163 - Storage Keepers(DP)

时间:2015-07-28 18:40:21      阅读:81      评论:0      收藏:0      [点我收藏+]

标签:acm   uva   

该题乍看好像背包问题,但是实际上实现起来就会发现细节上还是很不同的,  这小小的不同就可能导致完全错误,所以有必要对具体的推理过程进行归纳总结,以期找到动态规划的通用思路 。

首先,我们应该先完全明确状态方程表示的含义 。 对于该题,设d[i][j]表示i个守卫,看守j个仓库的最小安全系数的最大值 。其实说的简单一点,它就表示最小安全系数 。

一定要明确这一点,才能写出正确的递推关系 。     对于一个状态d[i][j] ,要怎么转移呢? 与背包类似,前i个守卫,这是一个天然的序,所以状态肯定要依赖于前i - 1 个守卫,另外,该题还有一点:使所有仓库的最小安全系数最大  。  那么首先,选不选第i个守卫? 所以d[i][j]的初始值是d[i-1][j],表示不选该守卫,然后假设选,选几个? 所以还要枚举k (1<=k<=j) 。然后就是状态转移了,先要求最小安全系数 , 由于该守卫看守了k个仓库,所以状态由d[i-1][j-k]来,还记得前面说的吗? 它表示的就是之前最小安全系数,所以现在的最小安全系数是 min(d[i-1][j-k],p[i]/k) 。 然后对于这个结果,d[i][j]取还是不取呢?因为要求尽量大, 所以不难写出 d[i][j] = max(d[i][j],min(d[i-1][j-k],p[i]/k)); 接下来是边界处理了。 通过观察状态转移方程,易知:d[i-1][0] = INF; 而其他值则设为0,。 为什么? 因为要求尽量大啊~

另外,该题还要求在此前提下守卫的最小总能力值 。 一开始我想在第一次DP的时候顺便求出来,后来发现这是不可行的,因为求这个值需要用到第一个答案,也就是说第一个答案没有求出来,是无法求第二个的 。 状态转移方程很简单f[i][j] = min(f[i][j],f[i-1][j-k]+p[i]); 然后就是注意好边界,这里不再赘述 。

细节参见代码:

#include<bits/stdc++.h>
using namespace std;
const int INF = 1000000000;
const int max_m = 35;
const int max_n = 105;
int n,m,p[max_m],d[max_m][max_n],f[max_m][max_n];
int main() {
    while(~scanf("%d%d",&n,&m)) {
        if(!n && !m) return 0;
        memset(d,0,sizeof(d));
        for(int i=0;i<=m;i++)
            for(int j=0;j<=n;j++) f[i][j] = INF;
        for(int i=1;i<=m;i++) scanf("%d",&p[i]);
        for(int i=1;i<=m;i++) {
            d[i-1][0] = INF;
            for(int j=1;j<=n;j++) {
                d[i][j] = d[i-1][j];
                for(int k=1;k<=j;k++) {
                    d[i][j] = max(d[i][j],min(d[i-1][j-k],p[i]/k));
                }
            }
        }
        for(int i=1;i<=m;i++) {
            f[i-1][0] = 0;
            for(int j=1;j<=n;j++) {
                f[i][j] = f[i-1][j];
                for(int k=1;k<=j;k++) {
                    if(p[i]/k >= d[m][n]) {
                        f[i][j] = min(f[i][j],f[i-1][j-k]+p[i]);
                    }
                }
            }
        }
        printf("%d %d\n",d[m][n],(d[m][n] == 0 ? 0 : f[m][n]));
    }
    return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

10163 - Storage Keepers(DP)

标签:acm   uva   

原文地址:http://blog.csdn.net/weizhuwyzc000/article/details/47107233

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!