POJ 1033 Defragment
根据http://hi.baidu.com/algorithm/item/d51b15f7a8ea1c0a84d278be这个开始练习ac,刚开始接触这道题时以为是道搜索题,读完之后深思了一下,感觉不需要套用一贯的dfs或者bfs,直接根据自己的思路走,然后注意一下效率问题就行了!可见算法注重灵活,而不是一贯的套用现有的模式。
利用题中示例:
簇号from[]:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
目前簇中内容应该在的簇号to[]:0 1 2 0 7 0 5 0 0 8 3 4 0 0 0 0 0 6 0 0
很自然的想法就是同时遍历from和to数组,如果from和to中内容相同,说明当前簇中内容不需要移动,否则为了优化必须进行移动,但是可以移动的前提是to所指的簇中内容为空,即from[to[i]]=0。可以先把满足移动条件的进行移动,由于移动之后,可能会引起其它簇满足移动条件,所以还需要再次遍历from和to,直到没有满足移动的簇。这个时候,有两种情况,一是达到优化状态,即from=to;另外一种是存在一个环,就如题中的5-7,7-5。针对第二种情况就是打破环,然后再次对满足移动条件的簇进行移动。多个嵌套循环就能解决了,但是这个过程使得需要多次遍历才能把所有满足移动条件的簇操作完全(由于移动导致了其他一些簇满足了移动条件后,需要第二次遍历才能将这些簇进行移动)。很明显会超时的。
有没有可能使得一次遍历之后,就能把不属于环的一些簇全部移动到位呢?答案是肯定的。
看下面代码,opt[]指在优化之后,簇i存放的是原来的簇opt[i]的内容。
#include <iostream>
#include <vector>
using namespace std;
int n, k;
vector<int> opt ;
vector<int> c2f;
int count;
bool moved = false;
void MoveBeginAt(int pos)
{
while( opt[pos] != 0 && !c2f[pos] )
{
int from = opt[pos];
int to = pos;
cout << from << " " << to << endl;
moved = true;
c2f[to] = c2f[from];
c2f[from] = 0;
opt[pos] = pos;
pos = from;
}
}
int MaxFreeIndex()
{
int i = c2f.size();
while( c2f[--i] );
return i;
}
int main()
{
while( cin >> n >> k )
{
opt.assign(n+1, 0);
c2f.assign(n+1, 0);
count = 0;
moved = false;
for(int i = 0; i < k; ++i)
{
int m; cin >> m;
for(int j = 0; j < m; ++j)
{
int c;
cin >> c;
opt[++count] = c;
c2f[c] = i + 1;
}
}
for(int i = 1; i <= count; ++i)
if( !c2f[i] )
MoveBeginAt( i );
int from = 0 ;
for(int i = 1; i <= count; ++i)
{
if( opt[i] != i )
{
if( !from )
from = i;
else if( opt[i] == from )
{
int to = MaxFreeIndex();
cout << from << " " << to << endl;
opt[i] = to;
c2f[to] = c2f[from];
c2f[from] = 0;
MoveBeginAt( from );
i = from ;
from = 0;
}
}
}
cout << (moved?"":"No optimization needed\n") ;
}
return 0;
}
另外还有一种利用栈的解法,也很巧妙,思路见 http://www.cnblogs.com/damacheng/archive/2010/09/24/1833983.html;代码实现如下:
#include <iostream>
#include <stack>
#include <vector>
using namespace std;
int n, k;
vector<int> opt;
stack<int> s;
int count ;
int MaxFreeIndex()
{
int i = opt.size() - 1;
while( opt[i] )
--i;
return i;
}
void Work()
{
bool moved = false;
for(int i = 1; i < opt.size(); ++i){
if( opt[i] && opt[i] != i ){
moved = true;
s.push( i );
int b = i, cur = opt[i];
while( true ){
s.push( cur );
if( !opt[cur] )
break;
else if( opt[cur] == b ){
int j = MaxFreeIndex();
cout << cur << " " << j << endl;
opt[j] = b;
opt[cur] = 0;
break;
}
cur = opt[cur];
}
int from, to = s.top();
s.pop();
while( !s.empty() ){
from = s.top();
cout << from << " " << to << endl;
opt[to] = opt[from];
to = s.top();
s.pop();
}
opt[to] = 0;
}
}
cout << (moved?"":"No optimization needed\n") ;
}
int main()
{
while( cin >> n >> k ){
opt.assign( n + 1, 0 );
count = 0;
for(int i = 0; i < k; ++i){
int m;
cin >> m;
for(int j = 0; j < m; ++j){
int c;
cin >> c;
opt[c] = ++count;
}
}
Work();
}
return 0;
}
POJ 1033 Defragment的更多相关文章
- POJ题目排序的Java程序
POJ 排序的思想就是根据选取范围的题目的totalSubmittedNumber和totalAcceptedNumber计算一个avgAcceptRate. 每一道题都有一个value,value ...
- 【动态规划】POJ 1161 & ZOJ1463 & XMU 1033 Brackets sequence
题目链接: http://acm.xmu.edu.cn/JudgeOnline/problem.php?id=1033 http://poj.org/problem?id=1141 ZOJ目前挂了. ...
- POJ1033 Defragment
题目来源:http://poj.org/problem?id=1033 题目大意: 某操作系统的文件系统中,所有的磁盘空间被分为N个大小相等的cluster,编号1至N.每个文件占用一个或多个clus ...
- [ACM训练] 算法初级 之 搜索算法 之 广度优先算法BFS (POJ 3278+1426+3126+3087+3414)
BFS算法与树的层次遍历很像,具有明显的层次性,一般都是使用队列来实现的!!! 常用步骤: 1.设置访问标记int visited[N],要覆盖所有的可能访问数据个数,这里设置成int而不是bool, ...
- POJ推荐50题
此文来自北京邮电大学ACM-ICPC集训队 此50题在本博客均有代码,可以在左侧的搜索框中搜索题号查看代码. 以下是原文: POJ推荐50题1.标记“难”和“稍难”的题目可以看看,思考一下,不做要求, ...
- 双向广搜 POJ 3126 Prime Path
POJ 3126 Prime Path Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 16204 Accepted ...
- POJ 3126 Prime Path (BFS)
[题目链接]click here~~ [题目大意]给你n,m各自是素数,求由n到m变化的步骤数,规定每一步仅仅能改变个十百千一位的数,且变化得到的每个数也为素数 [解题思路]和poj 3278类似.b ...
- POJ题目细究
acm之pku题目分类 对ACM有兴趣的同学们可以看看 DP: 1011 NTA 简单题 1013 Great Equipment 简单题 102 ...
- poj 3126 Prime Path bfs
题目链接:http://poj.org/problem?id=3126 Prime Path Time Limit: 1000MS Memory Limit: 65536K Total Submi ...
随机推荐
- JDK动态代理机制
JDK Proxy OverView jdk的动态代理是基于接口的.必须实现了某一个或多个随意接口才干够被代理.并且仅仅有这些接口中的方法会被代理. 看了一下jdk带的动态代理api,发现没有样例实在 ...
- NHibernate中使用memcache二级缓存
在NHibernate中使用memcache二级缓存 一.Windows下安装Memcache 1. 下载 http://jehiah.cz/projects/memcached-win32/ ...
- VMware Linux 下 Nginx
负载 VMware Linux 下 Nginx 安装配置 - nginx.conf 配置 [负载两个 Tomcat] (三) Weiseditor 2014-11-26 23:42 阅读:1 评论 ...
- - C#编程大幅提高OUTLOOK的邮件搜索能力!
原文:[原创] - C#编程大幅提高OUTLOOK的邮件搜索能力! 使用OUTLOOK, 你有没有遇到过上图的问题? 多达18419封邮件! 太多了, 每次想找一个邮件都非常耗时, 想办法解决这个问题 ...
- JS字符串数字互转
JS是一种弱类型的脚本语言,为变量赋值是会自动转换为相应的类型,例如: var a = 1; alert(a + 1);//结果为2 自动识别为数字类型进行数学运算 var b = '1'; aler ...
- SQL Server 2005中设置Reporting Services发布web报表的匿名访问
原文:SQL Server 2005中设置Reporting Services发布web报表的匿名访问 一位朋友提出个问题:集成到SQL Server 2005中的Reporting Services ...
- MVC之验证
MVC之验证 有时候我觉得,很多人将一个具体的技术细节写的那么复杂,我觉得没有必要,搞得很多人一头雾水的,你能教会别人用就成了,具体的细节可以去查MSDN什么的,套用爱因斯坦的名言:能在网上查到的就不 ...
- MobileProbe的使用
MobileProbe是CNZZ移动这块统计的一个产品,目前似乎分成了基础版和专业版.下载地址为: http://m.cnzz.com/?a=main&m=download&f=inf ...
- maven 启蒙
Maven是基于项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的软件项目管理工具.为了替代ANT的Apache开源项目.现在的项目越来越大.ANT已经不适用了. 1.部署m ...
- Windows Forms框架编程
<Windows Forms框架编程>节选 第九章 设计模式与原则 软件设计模式(Design pattern)是一套被反复使用的代码设计经验总结.使用设计模式是为了可重用代码.让代码 ...