[BOI2007]名次排序问题(sorting)
2017-06-09 10:30
281 查看
题目描述
已知参赛选手的得分,你的任务是按照得分从高到底给出选手的排名。遗憾的是,保存选手信息的数据结构只支持一种操作,即将一个选手从位置i移动到位置j,该移动不改变其他选手的相对位置,即如果i > j,位置j和位置i-1之间的选手的位置都比原来加1,相反如果 i < j,则位置i+1和位置j之间的选手的位置都比原来减一。上述移动的操作的代价定义为i+j,这里,位置编号从1开始。请你编程确定一个移动选手的步骤,将选手按照得分从高到低排序,并使整个移动过程的总代价最小。输入
文件sorting.in第一行为一个整数n(2<=n<=1000),表示选手的人数;接下来的n行,每行一个非负整数Si( 0<=Si<=1000000),表示一个选手的得分。你可以认为每人的得分是不同的。输出
文件sorting.out的第一行为一个整数,表示移动的次数,接下来的每一行表示一个移动步骤,每个移动步骤用两个整数i, j表示,表示位置i的选手移动到位置j, i和j之间有一个空格隔开。样例输入输出
soring.in5
20
30
5
15
10
sorting.out
2
2 1
3 5
附原题pdf下载
原题pdf下载(English)附原题数据下载
原题数据下载(已修改文件名,能被lemon等识别)题解
本身我不想写,因为我是按照《对一类动态规划问题的研究》(湖南省长沙市第一中学 徐源盛)这篇论文上的思路写的代码,但是网上都没有代码,于是我就写了代码,本着分享的原则,将这篇文章截取下来吧。同样这题属于当前决策对未来“行动”的费用影响只与当前决策有关的dp题目。
代码
#include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <map> #include <cassert> const int INF = 1e9; const int MAXN = 1000+10; typedef std::vector<int> vi; typedef std::pair<int,int> pii; typedef std::vector<pii> vpii; char used[MAXN+1]; int dp[MAXN+1][MAXN+1],prev[MAXN+1][MAXN+1]; int simulate(char *used,vi &p); void solve(vi &p); int main() { freopen("sorting.in","r",stdin); freopen("sorting.out","w",stdout); int n;std::map<int,int> byscore; scanf("%d",&n); for(int i=0;i<n;i++) { int val;scanf("%d",&val); byscore[val]=i; } int pos=0; vi p(n); for(std::map<int,int> ::reverse_iterator it=byscore.rbegin();it!=byscore.rend();it++,++pos) p[it->second] = pos; solve(p); return 0; } int simulate(char *used, vi &p) { int n = p.size(); int cost = 0; vpii moves; for (int i=n-1; i>=0; i--) { if (used[i]) continue; vi::iterator it = find(p.begin(),p.end(),i); int from_pos = distance(p.begin(),it) + 1; p.erase(it); it = find(p.begin(),p.end(),i+1); p.insert(it, i); int to_pos = distance(p.begin(),it) + 1; cost += from_pos + to_pos; moves.push_back(pii(from_pos,to_pos)); } for (int i=0; i<n; i++) assert(p[i] == i); printf("%d\n",(int)moves.size()); for (vpii::iterator it=moves.begin(); it!=moves.end(); ++it) printf("%d %d\n",it->first,it->second); return cost; } void solve(vi &p) { int n=p.size(); vi pos(n+1); p.push_back(n); for(int i=0;i<=n;i++) pos[p[i]]=i; for(int i=0;i<n;i++) dp [i]=INF; dp =0; for(int i=n-1;i>=0;i--) { int v=1; for(int j=0;j<pos[i];++j) if(p[j]<i) ++v; int v2=1; for(int h=0;h<=n;h++) { if(p[h]<i) ++v2; dp[i][h]=dp[i+1][h]+v+v2; prev[i][h]=h; } int add = 0; for (int k=pos[i]+1; k<=n; k++) { int tcost = dp[i+1][k]+add; if (dp[i][pos[i]] > tcost) { dp[i][pos[i]] = tcost; prev[i][pos[i]] = k; } if (p[k]<i) add += (i-p[k]); } } int mincost=INF,ind=-1; for(int i=0;i<=n;i++) if(dp[0][i]<mincost) { mincost=dp[0][i];ind=i; } for(int i=0;i<n;i++) { used[i]=(ind==pos[i])?1:0; ind=prev[i][ind]; } used =1; int tcost = simulate(used,p); }
相关文章推荐
- FR关于排序名次、分组排序名次问题
- #440 Div.2 D.Sorting the Coins 硬币排序问题
- 计算名次与按名次排序问题的算法优化
- Sorting Information with Comparable -Swift中实例的排序问题
- 在ListCtrl中进行排序问题
- 浅谈Java、MySQL的中文排序问题
- 今天遇到一个关于STL中排序的问题, 怀疑是sort的bug!
- 关于DataGrid的动态排序问题
- datagrid因排序造成的添加删除问题解决方案
- 有关SQL排序规则---------即"无法解决 equal to 操作的排序规则冲突"等等的菜问题.
- (原创)处理Sql server在不同环境下排序规则不一致的问题(二)
- sql排序规则问题,不能查询访问中文
- 名次排序
- DBGird排序的问题
- 排序出现的一个奇怪的问题,找出原因后差点吐血
- (原创)处理Sql server在不同环境下排序规则不一致的问题(三)
- 一个关于nvarchar字段排序,中英文混合排序的问题
- datagrid因排序造成的添加删除问题解决方案
- TOJ1002 全排序问题
- 关于按列排序的问题