ZJU2041 Gangsters - 动态规划 阶段选择
2008-04-08 16:32
246 查看
题目大意:
N个小偷先后来到一家饭店偷东西。饭店的门有K+1种[0-K]不同的打开程度,0表示关闭。如果门在Ti时刻的打开程度刚好等于第i个小偷的勇敢程度Si,那么小偷就会进去偷走Pi价值的物品;否则这个小偷就会直接走掉。饭店的门一个单位时间最多可以改变1的打开程度,如果有一个人适当地控制门的打开程度,问N个小偷最多能偷走多少东西。(N<=100,K<=100,T<=30000)
分析:
阶段很明显的动态规划。
最朴素的想法是用数组dp[t][k]表示t时刻门的打开程度是k,能偷走的最大价值。这个想法是正确的,但是由于时间T很大,效率很低。
可以按照小偷到来的时间排序一下。用dp[i]表示第i个小偷到来并且进入饭店,能偷走的最大价值。那么状态转移方程可以如下描述:
dp[i] = 0 // 若小偷i的勇敢程度大于他到来的时间( thief[i].s > thief[i].t )
= max{ thief[i].p ,
thief[i].p + dp[j] // 若小偷j的勇敢程度和小偷i的勇敢程度之差不超过他们到来的时间间隔
// if( (thief[i].t - thief[j].t) >= abs(thief[i].s - thief[j].s )
}
很容易写出程序。题目也很典型,主要是要考虑用时间作为阶段还是用小偷作为阶段。
许多题目都是这样,选择正确的阶段表示方法很重要,减少了许多不必要的计算。
-------------------------------------------------------------------------------------------
/*
ZJU2041 Gangsters
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define clr(a) memset(a,0,sizeof(a))
#define N 105
typedef struct{
int t,s,p;
}Thief;
Thief a
;
int f
;
int cmp(const void *a,const void *b){
return ((Thief*)a)->t - ((Thief*)b)->t;
}
inline int abs(int a){
return a>0?a:-a;
}
inline int max(int a,int b){
return a>b?a:b;
}
int main()
{
int i,j,k,m,n,T;
int ans;
scanf("%d",&T);
while(T--){
//input
scanf("%d%d%d",&n,&m,&k); //n thiefs, m states, k times
for(i=0;i<n;i++) scanf("%d",&a[i].t);
for(i=0;i<n;i++) scanf("%d",&a[i].p);
for(i=0;i<n;i++) scanf("%d",&a[i].s);
//sort
qsort(a,n,sizeof(Thief),cmp);
//DP
//f[i]表示第i个thief到来且进入商店获得的最大价值
//f[i]=max{a[i].p, f[j]+a[i].p (ai.t-a[j].t>=abs(a[i].s-a[j].s))}
clr(f);
ans=0;
for(i=0;i<n;i++){
if(a[i].s>a[i].t) continue;
f[i]=a[i].p;
for(j=0;j<i;j++)
if((a[i].t-a[j].t)>=abs(a[i].s-a[j].s)){
f[i]=max(f[i],f[j]+a[i].p);
}
ans=max(ans,f[i]);
}
//output
printf("%d/n",ans);
if(T) puts("");
}
return 0;
}
N个小偷先后来到一家饭店偷东西。饭店的门有K+1种[0-K]不同的打开程度,0表示关闭。如果门在Ti时刻的打开程度刚好等于第i个小偷的勇敢程度Si,那么小偷就会进去偷走Pi价值的物品;否则这个小偷就会直接走掉。饭店的门一个单位时间最多可以改变1的打开程度,如果有一个人适当地控制门的打开程度,问N个小偷最多能偷走多少东西。(N<=100,K<=100,T<=30000)
分析:
阶段很明显的动态规划。
最朴素的想法是用数组dp[t][k]表示t时刻门的打开程度是k,能偷走的最大价值。这个想法是正确的,但是由于时间T很大,效率很低。
可以按照小偷到来的时间排序一下。用dp[i]表示第i个小偷到来并且进入饭店,能偷走的最大价值。那么状态转移方程可以如下描述:
dp[i] = 0 // 若小偷i的勇敢程度大于他到来的时间( thief[i].s > thief[i].t )
= max{ thief[i].p ,
thief[i].p + dp[j] // 若小偷j的勇敢程度和小偷i的勇敢程度之差不超过他们到来的时间间隔
// if( (thief[i].t - thief[j].t) >= abs(thief[i].s - thief[j].s )
}
很容易写出程序。题目也很典型,主要是要考虑用时间作为阶段还是用小偷作为阶段。
许多题目都是这样,选择正确的阶段表示方法很重要,减少了许多不必要的计算。
-------------------------------------------------------------------------------------------
/*
ZJU2041 Gangsters
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define clr(a) memset(a,0,sizeof(a))
#define N 105
typedef struct{
int t,s,p;
}Thief;
Thief a
;
int f
;
int cmp(const void *a,const void *b){
return ((Thief*)a)->t - ((Thief*)b)->t;
}
inline int abs(int a){
return a>0?a:-a;
}
inline int max(int a,int b){
return a>b?a:b;
}
int main()
{
int i,j,k,m,n,T;
int ans;
scanf("%d",&T);
while(T--){
//input
scanf("%d%d%d",&n,&m,&k); //n thiefs, m states, k times
for(i=0;i<n;i++) scanf("%d",&a[i].t);
for(i=0;i<n;i++) scanf("%d",&a[i].p);
for(i=0;i<n;i++) scanf("%d",&a[i].s);
//sort
qsort(a,n,sizeof(Thief),cmp);
//DP
//f[i]表示第i个thief到来且进入商店获得的最大价值
//f[i]=max{a[i].p, f[j]+a[i].p (ai.t-a[j].t>=abs(a[i].s-a[j].s))}
clr(f);
ans=0;
for(i=0;i<n;i++){
if(a[i].s>a[i].t) continue;
f[i]=a[i].p;
for(j=0;j<i;j++)
if((a[i].t-a[j].t)>=abs(a[i].s-a[j].s)){
f[i]=max(f[i],f[j]+a[i].p);
}
ans=max(ans,f[i]);
}
//output
printf("%d/n",ans);
if(T) puts("");
}
return 0;
}
相关文章推荐
- M公斤食物,未来N天怎么选择收养小动物------动态规划
- 【动态规划之路径选择】
- 活动选择问题 (动态规划、贪心算法)
- JavaScript入门学习书籍的阶段选择
- 暑假集训第四周 阶段一 DP 动态规划 B - Bone Collector
- NBUT 动态规划专题——A - Gangsters
- uva 116 动态规划 多阶段决策问题 路径记录 lrj-P270
- 硬币选择问题-动态规划
- ZJU/ZOJ 1717 POJ 2030 The Secret Number 动态规划
- 递归,分治算法,动态规划和贪心选择的区别
- 关于标准分治、动态规划、贪婪选择三种策略的比较
- [动态规划]Zju1234--Chopsticks
- 如何在不同的阶段选择合适的学习资料
- [置顶] 活动选择问题(1)-动态规划分析
- ZJU1234 Chopsticks - 动态规划
- 玩互联网心得体会:创业阶段选择的重要性有舍才有得
- JavaScript入门学习书籍的阶段选择!
- 如何在不同的阶段选择合适的学习资料
- 选择数字(动态规划+单调队列)
- 分治策略、动态规划、贪婪选择以及递归之间的关系与区别(-)