这一题类似一个背包问题,在cost限制下实现value的最优。对于每个balloon (Pi,Hi),将它移动到height Hk这个choice即为背包问题中的选择某一个物品,对应的cost是|Hi-Hk|,value是ceil(Pi/Vk)。
因为一个balloon只能选择一个choice,这就类似于分组背包。本来以为直接用分组背包就可以了,但是分组背包是每一组至多选一个物品,而这里面每一组必须选一个物品。Then状态转移方程会不同。
dp[i][j]表示collect了前i个balloon,cost不超过j的最优解。那么遍历第i个balloon所有choice k,dp[i][j]=min(dp[i][j],max(dp[i-1][j-cost],value))。dp[i][j]=0 to k-1中选择某个choice的最优解,max(dp[i-1][j-cost],value)是选择当前choice k的least amount of time。这样就可以判断是否更改为choice k or 维持0 to k-1中某个之前的选择。
这一题最开始WA了,看别人的解法都是二分,还以为算法错了。于是开始看动态规划的最优性原理。o(╯□╰)o。if a1,a2,a3是dp[2][Q]的最优解,那么a1,a2一定是dp[1][Q-cost3]的最优解。Otherwise,假如b1,b2是dp[1][Q-cost3]的最优解,那么背包还可以放进去a3,dp[2][Q]的最优解就是b1,b2,a3了。
这一题大数据跑了半分钟,囧。
#include<iostream>
#include<stdio.h>
#include<cstdio>
#include<string>
#include<cmath>
#include<stdlib.h>
#include<algorithm>
#include<string.h>
#include<cstring>
#include<vector>
#include<queue>
#include<map>
#include<set>
using namespace std;
//2016 Round D Problem B. gBalloon
int T;
const int maxn=110;
int N;
int M;
int Q;
int P[maxn];
int H[maxn];
int V[maxn*10];
int dp[110][10010];
const int INF=0x3f3f3f3f;
int main()
{
freopen("B-large-practice.in","r",stdin);
// freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
scanf("%d",&T);
for(int ca=1;ca<=T;ca++)
{
memset(P,0,sizeof(P));
memset(H,0,sizeof(H));
memset(V,0,sizeof(V));
memset(dp,0x3f,sizeof(dp));
scanf("%d %d %d",&N,&M,&Q);
for(int i=0;i<M;i++)
{
scanf("%d",&V[i]);
}
for(int i=0;i<N;i++)
{
scanf("%d %d",&P[i],&H[i]);
}
for(int i=0;i<N;i++)
{
for(int j=0;j<=Q;j++)
{
// dp[i][j]=INF;
for(int k=0;k<M;k++)
{
if(V[k]==0)
{
continue;
}
else if(V[k]*P[i]>0)
{
continue;//can not reach (0, y)
}
else
{
int cost=abs(H[i]-k);
int value=(abs(P[i])+abs(V[k])-1)/abs(V[k]);//ceil(1.0*abs(P[i])/abs(V[k]));
if(j>=cost)
{
if(i==0)
{
dp[i][j]=min(dp[i][j],value);
}
else
{
// dp[i][j]=min(dp[i-1][j],max(dp[i-1][j-cost],value));
dp[i][j]=min(dp[i][j],max(dp[i-1][j-cost],value));
}
// cout<<P[i]<<" "<<V[k]<<" "<<endl;
// cout<<i<<" "<<j<<" "<<k<<" "<<cost<<" "<<value<<" "<<dp[i][j]<<endl;
}
}
}
}
}
if(dp[N-1][Q]==INF)
{
printf("Case #%d: IMPOSSIBLE\n",ca);
}
else
{
printf("Case #%d: %d\n",ca,dp[N-1][Q]);
}
}
return 0;
}