活动安排问题和全排列
一、区间贪心
活动安排问题:
活动 | a | b | c | d | e | f | g |
---|---|---|---|---|---|---|---|
开始 | 0 | 3 | 4 | 9 | 7 | 1 | 6 |
完成 | 2 | 7 | 7 | 11 | 10 | 5 | 8 |
如何安排下列活动使得使用的活动场所最少,并给出具体的安排方法。
思路:
要使使用活动场所最少,则应该尽可能在最大完成时间内使所有活动场所里都安排满活动。可以将每个活动抽象为N个区间,从中选择尽可能多不重合的区间。
#include <bits/stdc++.h>
using namespace std;
struct node{
int st,ed;//储存活动开始与结束时间
char flag;//标记自己原来位置
}act[10010];
bool cmp(node a,node b){
return a.st<b.st;
}
bool b[1010]={false};//储存被安排的活动编号
int area=0,j,t=0;
void greedy(int n,int st,int ed,bool b[]){
for(int i=0;i<n;i++){
if(b[i]==false){
b[i]=true;//默认将第一个没参加过的活动先安排
j=i;//记录最近一次加入b中的活动
printf("%c",act[i].flag);
t=1;
break;
}
}if(!t)return;//全部被选完退出
//依次检查活动i是否与当前已选择的活动相容
for(int i=j+1;i<n;i++){
if(act[i].st>=act[j].ed&&b[i]==false){
b[i]=true;//找到加入
printf("%c",act[i].flag);
j=i;
}
}cout<<endl;
area++; //利用贪心策略,安排了一个场地
}
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
cin>>act[i].st>>act[i].ed;
act[i].flag='a'+i;
}
sort(act,act+n,cmp);//按照活动的开始时间排序
for(int i=0;i<n;i++){
t=0;
greedy(n,act[i].st,act[i].ed,b);
if(!t)break;
}cout<<area;
return 0;
}
输出结果如下:
二、全排列算法
设R={r1,r2,r3,…,rn}是要进行排列的n个元素。其中元素r1,r2,…,rn可能相同。试设计一个算法,列出R的所有不同排列,请给出序列 abacd的全排列。
思路:
递归(注:此代码为非去重全排列,如果想要去重的话可直接使用C++函数库中的next_permutation)
#include <bits/stdc++.h>
using namespace std;
void swap(char *a,char *b)
{
char temp;
temp=*a;
*a=*b;
*b=temp;
}
void allarrange(char *str,int k,int len)
{
int i;
if(k==len)
{
printf("%s\n",str);
}
else{
for(i=k;i<=len;i++)
{
swap(str+i,str+k);
allarrange(str,k+1,len);
swap(str+i,str+k);//回溯
}
}
}
int main(){
char s[1000010];//字符串
cin>>s;
allarrange(s,0,strlen(s)-1);
return 0;
}
图示:
递归的过程不易理解,可以画递归树帮助理解。以"123"为例: