hdu1500
来源:互联网 发布:爱淘宝现金红包 编辑:程序博客网 时间:2024/05/18 17:45
看到这一题我刚开始想的时候也是好像觉得在哪里见过,但是想不起来,后来看到别人说的是hdu1421那个搬房子的题,两个题有很多的相似点,但是这一道题他的难度大一些,就是需要处理的地方稍微有一点拐弯。
题目大意是有N支筷子,K个人,N>=k*3那么每个人需要选择3支筷子,满足A<B<C,其中A,B两只筷子的差的平方将作为对着三支筷子取得好坏的一个因素,C不管,我们应当使每个人都有三支筷子,而且最后的总的平方和最小,求出这个最好笑的数字。
我们说一般的DP题都有一个公共的情况那就是:走到某一步的时候要或者不要,这两个方向一般就是你建立状态方程的突破口。下面假设f[i][j]表示到第i支快走的时候第j个人在取,那么对于第i支筷子只有两种要和不要,如果要的话也就是第j个人选中这支筷子,那么这支筷子只能和前面一支搭配,因为后面一支还没出来而且他们的长短是有序的,这时候就是f[i-2][j-1]+(a[i]-a[i-1])*(a[i]-a[i-1]),a[i]表示筷子长度,不要的话那就是f[i-1][j]。但是这样有一个缺点就是,如果有一个数字为0他就可以一直不要,最后就是0,为了一定能取到,我们事先就让他取,再判断。
还有一点就是这题必须从大到小,因为新来的一支是最大的,一定能取到,就是C,但是如果从大到小取到的就是最小的,多以不符合。
#include<iostream>
#include<stdio.h>
#include<cmath>
#include<cstdlib>
#include<string.h>
using namespace std;
int a[5005];
int f[5005][1005];
int main()
{
int T,k,N,i,j;
int num,sum;
cin>>T;
while(T--)
{
cin>>k>>N;
k+=8;
for(i=N;i>=1;i--)
scanf("%d",&a[i]);
memset(f,0,sizeof(f));
for(j=1;j<=k;j++)
{
i=j*3;
f[i][j]=f[i-2][j-1]+(a[i-1]-a[i])*(a[i-1]-a[i]);//这里是确保每一个人都要取筷子。
for(i++;i<=N;i++)
f[i][j]=min(f[i-1][j],f[i-2][j-1]+(a[i]-a[i-1])*(a[i]-a[i-1])); //i=3*j,也就是这时候一次性给你3根,然后你用后两个比较,前面一个就默认选择,如果是从小到大会有错误,如果这样大家都不理解的话,自己用数字带了试试看,就会明白的。
}
cout<<f[N][k]<<endl;
}
return 0;
}
- hdu1500
- HDU1500(DP)
- HDU1500 Chopsticks
- hdu1500 动态规划
- POJ 3041 Asteroids (匈牙利算法)
- Eclipse快捷键大全(转载)
- 结构体结合qsort排序
- poj 1003
- 火狐设置User Agent
- hdu1500
- 求两个或N个数的最大公约数(gcd)和最小公倍数(lcm)
- Spring MVC Thymeleaf
- 零基础unity3d游戏开发系列目录
- 约瑟夫环
- 查看证书 certmgr.msc
- BIEE用户使用代理账号身份访问Analytics页面
- 使用其他机器上的硬盘启动Centos5系统panic问题解决方法
- OSI七层参考模型每一层都有哪些协议