题意:有n个弹珠分别位于x轴上的一些位置,你可以选择其中的一些固定住(需要花费ci),当选择完毕之后,从最右面开始,弹珠会依次向左滚动直到遇到被固定住的弹珠(否则视为滚到无穷远处),计算花费+所有弹珠滚动的距离之和的最小值
思路:使用动态规划,首先最左边的弹珠肯定是要被固定住的,接着从左向右考虑每一个弹珠,固定每一个弹珠的花费都是可以直接得到的(花费-右边所有弹珠的个数*该弹珠到它右边相邻的一个弹珠的距离),接着就可以套用0-1背包的模型做了,注意一开始要先将弹珠根据它们的位置排序
AC代码:
#include <stdio.h> #include <climits> #include <algorithm> #include <iostream> typedef long long LL; using namespace std; struct node { LL x,c; }mar[3010]; LL dp[3010][3010] = {0}; bool cmp(node a,node b){return a.x<b.x;} int main() { int n; scanf("%d",&n); for(int i = 0;i<n;i++) scanf("%I64d%I64d",&mar[i].x,&mar[i].c); sort(mar,mar+n,cmp); for(int i = 1;i<n;i++) dp[0][0]+= mar[i].x-mar[0].x; dp[0][0]+=mar[0].c; for(int i = 1;i<n;i++) { dp[i][i] = LLONG_MAX; for(int j = 0;j<i;j++) { dp[i][j] = dp[j][j]; dp[i][i] = min(dp[i][i],dp[i][j]-(mar[i].x-mar[j].x)*(n-i)+mar[i].c); } } LL ans = LLONG_MAX; for(int i = 0;i<n;i++) { ans = min(ans,dp[n-1][i]); //cout << dp[n-1][i] << endl; } printf("%I64d\n",ans); return 0; }