【传送门:BZOJ2020】
简要题意:
约翰开车回家,遇到了双十一节,那么就顺路买点饲料吧。回家的路程一共有E 公里,这一路上会经过N 家商店,第i 家店里有Fi 吨饲料,售价为每吨Ci 元。约翰打算买K 吨饲料,他知道商家的库存是足够的,至少所有店的库存总和不会少于K。除了购买饲料要钱,运送饲料也是要花油钱的,约翰的卡车上如果装着X 吨饲料,那么他行驶一公里会花掉X 元,行驶D 公里需要DX 元。已知第i 家店距约翰所在的起点有Xi 公里,那么约翰在哪些商店买饲料运回家,才能做到最省钱呢?
输入格式:
• 第一行:三个整数K,E 和N,1 ≤ K ≤ 100, 1 ≤ E ≤ 350, 1 ≤ N ≤ 100
• 第二行到第N + 1 行:第i + 1 行有三个整数Xi,Fi 和Ci,0 < Xi < E; 1 ≤ Fi ≤ 100; 1 ≤Ci ≤ 10^6
输出格式:
• 单个整数:表示购买和运送饲料的最小费用之和
样例输入:
2 5 3
3 1 2
4 1 2
1 1 1
样例输出:
7
样例解释:
在离家较近的两家商店里各购买一吨饲料,则花在路上的钱是1 + 2 = 3,花在店里的钱是2 + 2 = 4
题解:
一眼贪心题,但是不会打,只好弄个DP水了过去
参考代码:
#include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<cmath> using namespace std; struct node { int x,f,c; }a[110]; int cmp(const void *xx,const void *yy) { node n1=*(node *)xx; node n2=*(node *)yy; if(n1.x>n2.x) return 1; if(n1.x<n2.x) return -1; return 0; } int f[110][110]; int main() { int k,e,n; scanf("%d%d%d",&k,&e,&n); for(int i=1;i<=n;i++) scanf("%d%d%d",&a[i].x,&a[i].f,&a[i].c); qsort(a+1,n,sizeof(node),cmp); memset(f,63,sizeof(f)); for(int i=0;i<=a[1].f;i++) f[1][i]=a[1].c*i; for(int i=2;i<=n;i++) { for(int p=0;p<=k;p++) { for(int q=0;q<=a[i].f;q++) { if(p+q>k) break; f[i][p+q]=min(f[i][p+q],f[i-1][p]+(a[i].x-a[i-1].x)*p+q*a[i].c); } } } printf("%d\n",f[n][k]+(e-a[n].x)*k); return 0; }