您的位置:首页 > 其它

POJ 3666 Making the Grade(动态规划)

2015-02-14 21:31 411 查看
大概题意:给出n个数字组成序列a,然后再找到一个序列b,从1至n,abs(a[i]-b[i])的总和最小,其中序列b是非严格单调序列,要么是要么是非递减序列,要么是非递增序列...

看完题目,河南省14年省赛题....大一下学期参加那场,这个题目做了好久果然没A出来,但是用的方法是构造出来b这个序列,先对原序列排序,然后开始构造成出第一个数字,以后每个数字要么是前一个数字要么就是自身...

现在想来原来的思路有几个漏洞。。比赛完之后当时也尝试去完成这个代码,但是只是记得样例,样例很好过...没找到题目,现在看到了想到的别的思路。

这个题目貌似是《挑战程序设计》,但是在家里手边没书...我程序中dp数组是一维的,但是是滚动数组,这个优化是01背包优化的思路...

大概思路:dp[i][j]就是完成了前i个,目标序列最后一个数字是排序后的第j个数字...不难想dp[i][j]其实就是dp[i-1][从1到j]里面损耗最小的+abs(a[i]-b[j])....题目说可费非增可非递减,排序两次比较麻烦,不如直接把原序列颠倒位置....

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std;
#define inf 1<<30
int dp[2333],n;
int Dp(int a[],int num[])
{
int ans=inf;
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
{
int t=inf;
for(int j=1;j<=n;j++)
{
t=min(t,dp[j]);//此时的dp[j]为dp[i-1][j]
dp[j]=t+abs(a[i]-num[j]);//此时的dp[j]代表的意义从dp[i-1][j]更新为dp[i][j]
}
}
for(int i=1;i<=n;i++)
ans=min(ans,dp[i]);
return ans;
}
int main()
{
int a[2333],b[2333],num[2333];
while(cin>>n)
{
for(int i=1;i<=n;i++)
{
cin>>a[i];
b[n-i+1]=a[i];
num[i]=a[i];
}
sort(num+1,num+n+1);
int ans;
ans=min(Dp(a,num),Dp(b,num));
cout<<ans<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: