Portal: http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1345

     http://codeforces.com/gym/100803/attachments  A题

好题!

坑不多,切入比较难

一开始的想法是暴力,由于求得是最小解且此图太大无边界,所以不能DFS,首先想到BFS

解法1 BFS+STL queue

 #include<iostream>
#include<algorithm>
#include<set>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<queue>
using namespace std;
#define FOR(i,j,k) for(int i=j;i<=k;i++)
#define FORD(i,j,k) for(int i=j;i>=k;i--)
#define LL long long
#define SZ(x) x.size()
int vis[];
int x,k,n,m,s,ans,start,end1,end2,dight;
int bfs()
{
queue<int> q1,q2;
q1.push(start);
q2.push();
vis[start]=;
while(q1.front()!=end1&&q1.front()!=end2)
{
int fr=q1.front();
int fv=q2.front();
FOR(i,,n-)
{
if((fr&(<<i))&&!(fr&(<<(i+))))
{
ans=fr+(<<i);
if(!vis[ans]) {vis[ans]=;q1.push(ans);q2.push(fv+);}
}
else if(!(fr&(<<i))&&(fr&(<<(i+))))
{
ans=fr-(<<i);
if(!vis[ans]) {vis[ans]=;q1.push(ans);q2.push(fv+);}
}
}
q1.pop();
q2.pop();
}
return q2.front()-;
}
int main()
{
cin>>n>>m;
dight=;
FORD(i,n-,)
{
cin>>x;
start+=x<<i;
}
int c=n;
FOR(i,,m)
{
cin>>x;
FOR(j,,x)
{
c--;
end1+=dight<<c;
end2+=(-dight)<<c;
}
dight^=;
}
cout<<bfs()<<endl;
return ;
}

蛋疼的代码

解法2 BFS+手写queue

 #include<iostream>
#include<algorithm>
#include<set>
#include<cstdio>
#include<cstdlib>
#include<cmath>
//#include<queue>
using namespace std;
#define FOR(i,j,k) for(int i=j;i<=k;i++)
#define FORD(i,j,k) for(int i=j;i>=k;i--)
#define LL long long
#define SZ(x) x.size()
int vis[];
int x,k,n,m,s,ans,start,end1,end2,dight; int bfs()
{
int q1[];int L1=;int R1=;
int q2[];int L2=;int R2=;
q1[++R1]=start;
q2[++R2]=;
vis[start]=;
while(q1[L1]!=end1&&q1[L1]!=end2)
{
int fr=q1[L1];
int fv=q2[L2];
FOR(i,,n-)
{
if((fr&(<<i))&&!(fr&(<<(i+))))
{
ans=fr+(<<i);
if(!vis[ans]) {vis[ans]=;q1[++R1]=ans;q2[++R2]=fv+;}
}
else if(!(fr&(<<i))&&(fr&(<<(i+))))
{
ans=fr-(<<i);
if(!vis[ans]) {vis[ans]=;q1[++R1]=ans;q2[++R2]=fv+;}
}
}
L1++;
L2++;
}
return q2[L2]-;
}
int main()
{
cin>>n>>m;
dight=;
FORD(i,n-,)
{
cin>>x;
start+=x<<i;
}
int c=n;
FOR(i,,m)
{
cin>>x;
FOR(j,,x)
{
c--;
end1+=dight<<c;
end2+=(-dight)<<c;
}
dight^=;
}
cout<<bfs()<<endl;
return ;
}

同样的代码

比较同样情况下STL的queue和手写的queue,我发现STL的queue内存比手写的多了4KB

这是个严重的问题,因为STL经常pop元素,是动态的,它的内存一定较小,但即便在手写的queue固定大小为8e5个int的情况下,仍然多4KB,即1e3个int

STL的queue在此题理论上能够最多有16384个元素,所以事实上同等长度的queue所用内存相当于3到4倍同等int

所以,我们应该谨慎使用STL,为保险起见,用queue时数据输入的极限容量不得多于1e7,即1/10int在32768KB下容量左右

在解法1/2的代码中使用了位运算的黑科技

FORD(i,n-,)
{
cin>>x;
start+=x<<i;
}
int c=n;
FOR(i,,m)
{
cin>>x;
FOR(j,,x)
{
c--;
end1+=dight<<c;
end2+=(-dight)<<c;
}
dight^=;
} /// if((fr&(<<i))&&!(fr&(<<(i+))))
{
ans=fr+(<<i);
if(!vis[ans]) {vis[ans]=;q1[++R1]=ans;q2[++R2]=fv+;}
}
else if(!(fr&(<<i))&&(fr&(<<(i+))))
{
ans=fr-(<<i);
if(!vis[ans]) {vis[ans]=;q1[++R1]=ans;q2[++R2]=fv+;}
}

神奇的做法

其中(fr&(1<<i))&&!(fr&(1<<(i+1)))最妙

fr&(1<<i)表示判断fr的二进制表示中第i位是否为1(黑科技中利用了c++非0为真的机制)

这样使用黑科技的原因是这题中交换相同的二进制位是没有意义

所以仅仅交换01和10来产生当前数字的邻居

解法3 贪心

思路 先处理出start[]和两个可能的终点end1[] end2[]

再判断start到end的变换是否可行(检查01数量)

若可行,用K从1到n(maxlength)迭代

则对于 start[K]与endx[K]

若start[K]与endx[K]相同 不做任何操作

若start[K]与endx[K]不相同 则找到离K最近的J(J<K)使得 start[J]!=start[K] 使start[J]与start[--J]不停交换使得J最终等于K以完成start[K]与endx[K]相同的任务

此时操作增加了J-K次

 #include<iostream>
#include<algorithm>
#include<set>
#include<cstdio>
#include<cstdlib>
#include<cmath>
//#include<queue>
using namespace std;
#define FOR(i,j,k) for(int i=j;i<=k;i++)
#define FORD(i,j,k) for(int i=j;i>=k;i--)
#define LL long long
#define SZ(x) x.size()
int start[],end1[],end2[];
int x,c,k,n,m,s,ans,ans1,ans2,dight;
bool check1()
{
int s[]={,};
FOR(i,,n)
s[start[i]]++;
FOR(i,,n)
s[end1[i]]--;
if(s[]==&&s[]==) return true; else return false;
}
bool check2()
{
int s[]={,};
FOR(i,,n)
s[start[i]]++;
FOR(i,,n)
s[end2[i]]--;
if(s[]==&&s[]==) return true; else return false;
}
int find1(int xx,int x)
{
int ss=x;
while(ss<=n&&end1[ss]!=xx)
ss++;
if(ss==n+) return ; else return ss;
}
int find2(int xx,int x)
{
int ss=x;
while(ss<=n&&end2[ss]!=xx)
ss++;
if(ss==n+) return ; else return ss;
}
int main()
{
cin>>n>>m;
dight=;
FOR(i,,n)
cin>>start[i];
FOR(i,,m)
{
cin>>k;
FOR(j,,k)
{
c++;
end1[c]=dight;
end2[c]=-dight;
}
dight^=;
}
bool flag1=check1();
bool flag2=check2();
int zz=;
if(flag1)
while(zz!=n)
{
zz++;
if(end1[zz]!=start[zz])
{
int findd=find1(start[zz],zz);
end1[findd]^=;
end1[zz]^=;
ans1+=findd-zz;
}
}
zz=;
if (flag2)
while(zz!=n)
{
zz++;
if(end2[zz]!=start[zz])
{
int findd=find2(start[zz],zz);
end2[findd]^=;
end2[zz]^=;
ans2+=findd-zz;
}
}
if(flag1&&flag2) cout<<min(ans1,ans2)<<endl;
else if(flag1) cout<<ans1<<endl;
else cout<<ans2<<endl;
return ;
}

烂代码

coderforces Gym 100803A/Aizu 1345/CSU 1536/UVALive 6832 Bit String Reordering(贪心证明缺)的更多相关文章

  1. 贪心 UVALive 6832 Bit String Reordering

    题目传送门 /* 贪心:按照0或1开头,若不符合,选择后面最近的进行交换.然后选取最少的交换次数 */ #include <cstdio> #include <algorithm&g ...

  2. UVaLive 6832 Bit String Reordering (模拟)

    题意:给定一个01序列,然后让你你最少的操作数把这它变成目标. 析:由于01必须是交替出现的,那么我们就算两次,然后取最值. 代码如下: #pragma comment(linker, "/ ...

  3. csu - 1536: Bit String Reordering (模拟)

    http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1536 不知道为何怎么写都写不对. 这题可以模拟. 虽然题目保证一定可以从原串变成目标串,但是不一定 ...

  4. ACM学习历程—CSU 1216 异或最大值(xor && 贪心 && 字典树)

    题目链接:http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1216 题目大意是给了n个数,然后取出两个数,使得xor值最大. 首先暴力枚举是C(n,  ...

  5. UVaLive 6609 Meeting Room Arrangement (贪心,区间不相交)

    题意:给定 n 个区间,让你选出最多的区间,使得每个区间不相交. 析:贪心题,贪心策略是按右端点排序,然后按着选即可. 代码如下: #pragma comment(linker, "/STA ...

  6. UVALive 4031 Integer Transmission(贪心 + DP)

    分析:求出最大值和最小值比较简单,使用贪心法,求最小值的时候我们让所有的0尽可能的向后延迟就可以了,求最大值则相反. 关键在于求出可以组合出的数字个数. 这就是组合数学版的dp了,我们让dp[i][j ...

  7. UVaLive 4628 Jack's socks (贪心)

    题意:给定一个无向图,让你把所有点的和它的任意一个相邻点匹配起来,问你是方案是不是唯一,如果是,则输出方案. 析:贪心,很容易知道,如果一个点的度数是 1,那么它只有一个相邻点,这样的话,我们就可以把 ...

  8. UVALive - 4636 Cubist Artwork(贪心)

    题目链接 题意 给出正视图和侧视图,判断最少用几个立方体 分析 若存在高度相同的立方块,则以数目多的那面为准. #include <iostream> #include <cstdi ...

  9. UVALive 3971 Assemble(二分+贪心)

    本题思路不难,但是要快速准确的AC有点儿考验代码功力. 看了大白书上的标程,大有所获. 用map和vector的结合给输入分组,这个数据结构的使用非常精美,恰到好处. #include<iost ...

随机推荐

  1. 伪元素 before 和 after 初探

    伪元素 before 和 after 初探 使用了 CodePen 做演示,欢迎点击预览 定义 首先来看 MDN 的定义: ::before 创建一个伪元素,作为已选中元素的第一个子元素,常通过 co ...

  2. Mac结合Docker开发

    Mac结合Docker开发 前几天在看Java并发实战时,在Mac上写了一个示例,结果运行后无法按照书本上运行.主要是有些命令,在Mac和Linux是有区别的,比如top, Mac上是不支持-Hp,意 ...

  3. 【Vue】---- 手动封装on,emit,off

    一.概念 1. $on("事件名称",回调函数) 事件绑定,一个事件名称上面可能绑定多个函数 2. $emit("事件名称",需要传递的值) 事件触发时,会触发 ...

  4. 如何从普通程序员晋升为架构师 面向过程编程OP和面向编程OO

    引言 计算机科学是一门应用科学,它的知识体系是典型的倒三角结构,所用的基础知识并不多,只是随着应用领域和方向的不同,产生了很多的分支,所以说编程并不是一件很困难的事情,一个高中生经过特定的训练就可以做 ...

  5. R语言实战(一) R语言介绍

    从2018年秋季(大二上学期)开始接触R语言,曾在2019年寒假读过一遍本书的第一版,感觉受益匪浅,之后遇到问题也曾回头来查阅这本书,前几天刚学习过Simulink,趁现在有空再来温习这本书,回顾一下 ...

  6. C语言程序设计(三) 简单的算术运算和表达式

    第三章 简单的算术运算和表达式 算数运算符:一元.二元.三元(条件运算符) 1/2是整型除法,1.0/2是浮点数除法 求余运算(%)限定参与运算的两个操作数必须为整数,不能对两个实型数据进行求余运算 ...

  7. SpringBoot——Cache使用原理及Redis整合

    前言及核心概念介绍 前言 本篇主要介绍SpringBoot2.x 中 Cahe 的原理及几个主要注解,以及整合 Redis 作为缓存的步骤 核心概念 先来看看核心接口的作用及关系图: CachingP ...

  8. [日志分析]Graylog2采集mysql慢日志

    之前聊了一下graylog如何采集nginx日志,为此我介绍了两种采集方法(主动和被动),让大家对graylog日志采集有了一个大致的了解. 从日志收集这个角度,graylog提供了多样性和灵活性,大 ...

  9. 【Python】2.19学习笔记 成员运算符,身份运算符,运算符优先级

    成员运算符 暂时不会用,等学链表时再补充 \(in\) 与 \(not in\) \(in\):如果在指定序列中找到指定值,则返回\(true\) \(not in\):如果在指定序列中找到指定值,则 ...

  10. DOTNET CORE源码分析之IOC容器结果获取内容补充

    补充一下ServiceProvider的内容 可能上一篇文章DOTNET CORE源码分析之IServiceProvider.ServiceProvider.IServiceProviderEngin ...