算法设计与分析_01
【学习通】
选择
【编程题】
要求
交电子版,命名格式:学号-姓名。包含代码、测试数据、程序截图。
贪心法
简述贪心法的基本思想、特点、求解过程。
基本思想:保证每次都是局部最优解,从而使全局接近最优。
特点:可以解决贪心选择性质和最优子结构性质问题的最优解问题。
求解过程:从某个初始解出发,采用迭代的过程,当可以向目标前进一步时,就根据局部最优策略,得到一部分解,缩小问题规模,将所有解综合起来得到最优解。
使用贪心法,编程实现会议安排问题。
#include <iostream>
#include <alogorithm>
#include <cstring>
using namespace std;
struct Meet
{
int beg;
int end;
int num;
} meet[1000];
class setMeet{
public:
void init();
void solve();
private:
int n,ans;
}
void setMeet::init()
{
int s,e;
cout<<"输入会议总数:"<<end1;
cin>>n;
int i;
cout<<"输入会议的开始时间和结束时间,以空格分开"<<end1;
for(i=0;i<n;i++)
{
cin>>s>>e;
meet[i].beg=s;
meet[i].end=e;
meet[i].num=i+1;
}
}
bool cmp(Meet x,Meet y)
{
if(x.end==y.beg)
return x.beg>y.beg;
return x.beg<y.beg;
}
void setMeet::solve()
{
sort(meet,meet+n,cmp);
cout<<"排完序的会议时间如下:"<<end1;
int i:
cout<<"会议编号"<<"开始时间"<<"结束时间"<<end1;
for(i=0;i<n;i++)
{
cout<<" "<<meet[i].num<<"\t\t"<<meet[i].beg<<"\t"<<meet[i].end<<end1;
}
cout<<"-----------------------------------------------------------"<<end1;
cout<<"选择的会议的过程:"<<end1;
cout<<"选择第"<<meet[0].num<<"个会议"<<end1;
ans=1;
int last=meet[0].end;
for(i=1;i<n;i++)
{
if(meet[i].beg>=last)
{
ans++;
last=meet[i].end;
cout<<"选择第"<<meet[i].num<<"个会议"<<end1;
}
}
}
int main()
{
setMeet sm;
sm.init();
sm.slove();
return 0;
}
分治法
简述分治法的基本思想、特点、求解过程。
基本思想:将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。
特点:将问题分解为若干个相同的子问题,降低问题的解决难度。
使用分治法,编程找出n个数中第k小的数字。
#include <iostream>
using namespace std;
int partition(int[], int, int);
int Select(int[], int, int, int);
int main()
{
int n, m;
int l, r, k;
int v[100002];
int d[100002];
cin >> n >> m;
for (int i = 1; i <= n; i++) cin >> v[i];
while (m--)
{
cin >> l >> r >> k;
for (int j = l; j <= r; j++) d[j] = v[j];
cout << Select(d, l, r, k) << endl;
}
return 0;
}
//一次快速排序
int partition(int s[], int l, int r)
{
if (l < r)
{
int i = l;
int j = r;
int x = s[i];
while (i < j)
{
while (i < j && s[j] >= x) j--;
if (i < j) s[i++] = s[j];
while (i < j && s[i] < x) i++;
if (i < j) s[j--] = s[i];
}
s[i] = x;
return i;
}
return -1;
}
//分治找K-th Number
int Select(int s[], int l, int r, int k)
{
if (l > r) return -1;
if (l == r) return s[l];
//得到中间数的下标
int i = partition(s, l, r);
//j为左区间长度
int j = i - l + 1;
//位置大就在左区间找,否则就在右区间找
if (j == k) return s[i];
else if (j > k) return Select(s, l, i, k);
else return Select(s, i+1, r, k-j);
}

浙公网安备 33010602011771号