HDU-1421 搬寝室(递推,DP,数学)2017寒假集训
题意:从n个物品里挑出2k个物品,每次拿两个,花费是两物品重量的平方差,求最小的花费
数据范围:2 <= 2*k <= n < 2000,重量不超过2^15
思路:考虑有确定的2k个物品,确定一种顺序使花费最小
可以证明,按重量对这2k个物品排序,然后相邻物品两两配对花费是最小的
设总花费是(a-b) ^ 2 + (c-d) ^ 2 + .... etc,去括号得到a^2+b^2+...一串平方和为定值
又当a<b<c<d时,ab+cd < ad+bc,就证明了这个结论
考虑dp[i][j]表示前i个物品,取走了j对物品时的最小花费,对于每个i,决策有取这一对和不取这一对,转移为:dp[i][j] = min(dp[i-1][j], dp[i-2][j-1]+cost(i, i-1))
答案为dp[n][k]
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define INF 0x3f3f3f3f 5 using namespace std; 6 7 const int mx = 1010; 8 int a[mx*2], dp[2*mx][mx]; 9 10 int solve(int i, int j){ 11 int k = a[i]-a[j]; 12 return k*k; 13 } 14 15 int main(){ 16 int n, k; 17 while (scanf("%d%d", &n, &k) == 2){ 18 memset(dp, INF, sizeof(dp)); 19 for (int i = 1; i <= n; i++){ 20 scanf("%d", &a[i]); 21 dp[i][0] = 0; 22 } 23 dp[0][0] = 0; 24 sort(a+1, a+n+1); 25 for (int i = 2; i <= n; i++) 26 for (int j = 1; j <= k; j++) 27 dp[i][j] = min(dp[i-1][j], dp[i-2][j-1]+solve(i, i-1)); 28 printf("%d\n", dp[n][k]); 29 } 30 return 0; 31 }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
· 《HelloGitHub》第 106 期
· Spring AI + Ollama 实现 deepseek-r1 的API服务和调用
· 数据库服务器 SQL Server 版本升级公告
· 深入理解Mybatis分库分表执行原理
· 使用 Dify + LLM 构建精确任务处理应用