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 ...
随机推荐
- jquery.validate 以alert方式显示错误方法
$.validator.setDefaults({ submitHandler: function() { alert("submitted!");return false; } ...
- Java泛型和集合之泛型VS模板
Java的泛型很像C++中的模板,说到Java 泛型和C++中的模板的关系时,有两个重要的方面需要被考虑到:语法和语义.语法看起来是相似的,可是语义却明显是不同的. 在语法上讲,选择尖括号 是因为他 ...
- D3D 光照和材料 小样例
1.实现一个旋转的圆柱体,体现d3d光照效果 2.程序实现 #pragma once #pragma comment(lib,"winmm.lib") #pragma commen ...
- 安装Visual Studio 2010 - 初学者系列 - 学习者系列文章
本文讲述如何安装Visual Studio 2010开发工具. 首先,通过下列地址获取Visual Studio 2010的副本 1.开始页面 2.欢迎页 3.这里选择 自定义 ,选择安装路径 4.这 ...
- WebIM(4)----Comet的特殊之处
WebIM系列文章 在一步一步打造WebIM(1)一文中已经使用Comet实现了一个简单的WebIM,那么,Comet究竟和一般的打开网页有何区别,本文将通过编写一个简单的HTTP服务器来说明两者的区 ...
- 【转】Android实现推送方式解决方案
本文介绍在Android中实现推送方式的基础知识及相关解决方案.推送功能在手机开发中应用的场景是越来起来了,不说别的,就我们手机上的新闻客户端就时不j时的推送过来新的消息,很方便的阅读最新的新闻信息. ...
- 在Android中自动实现横竖屏切换的问题
http://developer.android.com/training/basics/supporting-devices/screens.html参照Google推荐的做法 在你项目的res 文 ...
- jquery表格datagrid单元格显示图片及分页使用
要想达到自定义显示表格框的目的比如显示图片,超链接,按钮的形式,只需要给列添加formatter属性即可,比如显示图片: columns: [[ ...
- Ecological Premium - UVa10300
欢迎访问我的新博客:http://www.milkcu.com/blog/ 原文地址:http://www.milkcu.com/blog/archives/uva10300.html 题目描述 Pr ...
- C#版考题
某软件大赛C#版考题整理——[单选题] 一.单选题(10小题共20.0分) 1. 以下JavaScript代码的正确输出结果是:(). 1 2 3 4 5 6 7 8 9 <script t ...