动态规划练习1
2017-07-25 14:15
162 查看
题目描述:
在ls森林里有一只很能砍树的樵夫lw,他左手扛狂暴药水,右手握着雷神之斧,白天砍树,晚上喝狂暴药水。这天他接到了国王给他的一个任务:砍掉两颗树。设两颗树的耐久值都为x(各自独立)。而lw有n(n<=100)把不同的斧头,设第i把斧头每a[i]秒种能消耗第一棵树1点耐久值,或者每b[i]秒消耗第二棵树1点耐久值。对于一个斧头来说,砍树对象可以变换,即可以砍a[i]秒a,再砍b[i]秒b。对于一棵树来说,可以同时被多个斧头砍。当两颗树的耐久值都小于等于0时任务完成。lw想问你完成的最短时间是多少。
输入格式:
第一行两个数,分别为n和x,即斧头数和树的耐久值,接下来n行每行两个数,第i+1行的两个数为a[i]和b[i]。
输出格式:
第一行一个数t,即完成任务的最少时间。
样例输入:tree.in
2 20
5 1
1 5
样例输出:tree.out
20
数据范围:
对于30%的数据,n<=10,x<=30,a[i],b[i]<=20。
对于100%的数据,n<=100,x<=100,a[i],b[i]<=100。
[b]题解:[/b]
[b]考虑f[i][j]表示前i个斧头砍1的j块,还可以砍2的最多块数。[/b]
[b]d[i][0]存砍1的效率,d[i][1]存砍2的效率[/b]
[b]f[i][j]=max(f[i][j],f[i-1][j-k]+(day-d[i][0]*k)/d[i][1]);[/b]
[b]f[i-1,j-k]是前i-1个斧头砍j-k个1还能砍几个2。day-d[i,0]*k是第i个斧头砍k个1还剩的时间[/b]
[b](day-d[i][0]*k)/d[i][1]第i个斧头还能砍几个2[/b]
[b]所以f[i-1][j-k]+(mid-d[i][0]*k)/d[i][1]是前i个斧头一共可以砍几个2[/b]
[b]显然是成立的。[/b]
[b]而对于day的值,可以证明,f是随day单调递增的。我们可以二分这个day值,每次用DP检验。若f
[x]>=x,r=mid-1;f
[x]<x,l=mid+1。[/b]
在ls森林里有一只很能砍树的樵夫lw,他左手扛狂暴药水,右手握着雷神之斧,白天砍树,晚上喝狂暴药水。这天他接到了国王给他的一个任务:砍掉两颗树。设两颗树的耐久值都为x(各自独立)。而lw有n(n<=100)把不同的斧头,设第i把斧头每a[i]秒种能消耗第一棵树1点耐久值,或者每b[i]秒消耗第二棵树1点耐久值。对于一个斧头来说,砍树对象可以变换,即可以砍a[i]秒a,再砍b[i]秒b。对于一棵树来说,可以同时被多个斧头砍。当两颗树的耐久值都小于等于0时任务完成。lw想问你完成的最短时间是多少。
输入格式:
第一行两个数,分别为n和x,即斧头数和树的耐久值,接下来n行每行两个数,第i+1行的两个数为a[i]和b[i]。
输出格式:
第一行一个数t,即完成任务的最少时间。
样例输入:tree.in
2 20
5 1
1 5
样例输出:tree.out
20
数据范围:
对于30%的数据,n<=10,x<=30,a[i],b[i]<=20。
对于100%的数据,n<=100,x<=100,a[i],b[i]<=100。
[b]题解:[/b]
[b]考虑f[i][j]表示前i个斧头砍1的j块,还可以砍2的最多块数。[/b]
[b]d[i][0]存砍1的效率,d[i][1]存砍2的效率[/b]
[b]f[i][j]=max(f[i][j],f[i-1][j-k]+(day-d[i][0]*k)/d[i][1]);[/b]
[b]f[i-1,j-k]是前i-1个斧头砍j-k个1还能砍几个2。day-d[i,0]*k是第i个斧头砍k个1还剩的时间[/b]
[b](day-d[i][0]*k)/d[i][1]第i个斧头还能砍几个2[/b]
[b]所以f[i-1][j-k]+(mid-d[i][0]*k)/d[i][1]是前i个斧头一共可以砍几个2[/b]
[b]显然是成立的。[/b]
[b]而对于day的值,可以证明,f是随day单调递增的。我们可以二分这个day值,每次用DP检验。若f
[x]>=x,r=mid-1;f
[x]<x,l=mid+1。[/b]
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> using namespace std; int f[101][101],n,x,a[101],b[101]; int gi() { int ans=0,f=1; char i=getchar(); while(i<'0'||i>'9'){if(i=='-')f=-1;i=getchar();} while(i>='0'&&i<='9'){ans=ans*10+i-'0';i=getchar();} return ans*f; } bool judge(int mid) { int i,j,k; memset(f,200,sizeof(f)); f[0][0]=0; for(i=1;i<=n;i++) for(j=0;j<=x;j++) for(k=0;k<=min(j,mid/a[i]);k++) f[i][j]=max(f[i][j],f[i-1][j-k]+(mid-k*a[i])/b[i]); return f [x]>=x; } int main() { freopen("tree.in","r",stdin); freopen("tree.out","w",stdout); int i,j; n=gi();x=gi(); for(i=1;i<=n;i++){a[i]=gi();b[i]=gi();} int l=0,r=20000,ans=0; while(l<=r) { int m=(l+r)>>1; if(judge(m))ans=m,r=m-1; else l=m+1; } printf("%d",ans); return 0; }
相关文章推荐
- 动态规划练习——最大上升子序列和
- 动态规划练习1--Unique Paths
- 算法练习 动态规划 硬币找零
- 动态规划入门练习
- 算法练习---跳跃游戏二(动态规划)
- HDU 5389 Zero Escape(动态规划)——多校练习8
- 动态规划练习 14
- 动态规划初级练习(一):ZigZag
- 动态规划练习一 06:登山
- 动态规划练习一 最长上升子序列
- 动态规划练习一—2最大子矩阵
- 动态规划练习一 21题
- 动态规划练习一 三角形最佳路径问题
- 动态规划练习02:最大子矩阵
- 动态规划(练习题目,)
- 编程练习-动态规划(矩阵乘法)
- poj 动态规划专题练习
- 动态规划练习 4
- 动态规划练习一 16:踩方格
- 动态规划练习一 02:最大子矩阵