i | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
si | 1 | 3 | 0 | 5 | 3 | 5 | 6 | 8 | 8 | 2 | 12 |
fi | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
A)描述贪心选择标准
以第一个活动作为起点(因为他是最早结束的,这样才可以尽可能增加多次活动的“潜力”),总是选择满足兼容条件下的最早结束的活动,因为这样可以使得剩下的时间资源可以更多的其他活动使用,这种选择方式一定可以选出最大兼容活动数。
// ConsoleAppGreedyTest1.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "iostream"
using namespace std;
#define len 11
int GreedyActivitySelector(int *s,int *f,int *A);
int _tmain(int argc, _TCHAR* argv[])
{
int Si[len] = { 1, 3, 0, 5, 3, 5, 6, 8, 8, 2, 12 };//开始时间
int Fi[len] = { 4, 5, 6, 7, 9, 9, 10, 11, 12, 14, 16 };//结束时间
int A[len] = { 0 };//兼容活动子集
int l = 0;
l=GreedyActivitySelector(Si, Fi, A);//获取最大活动兼容个数
for (int i = 0; i < l;i++)
{
cout << A[i] << " ";
}
cout << endl;
system("pause");
return 0;
}
int GreedyActivitySelector(int *s, int *f, int *A)
{
int longlen = 0;
A[0] = 0;//直接选取第一个活动作为最大兼容活动集的起点
int k = 0;//记录最近加入的活动的下标
int count = 1;
for (int m = 1; m < len;m++)
{
if (s[m]>f[k])//s[m]是下一个活动的开始时间,f[k]是上一个活动的结速时间,我们总是希望找到下一个活动的开始时间比上一个的结束时间大,就可以了
{
A[count] = m;
count++;
k = m;
}
}
return count;
}
给定一个整型数组, 求这个数组的最长严格递增子序列的长度。 譬如序列1 2 2 4 3 的最长严格递增子序列为1,2,4或1,2,3.他们的长度为3。
输入可能包含多个测试案例。
对于每个测试案例,输入的第一行为一个整数n(1<=n<=100000):代表将要输入的序列长度
输入的第二行包括n个整数,代表这个数组中的数字。整数均在int范围内。
对于每个测试案例,输出其最长严格递增子序列长度。
4 4 2 1 3 5 1 1 1 1 1
2 1
#include
#include "vector"
using namespace std;
int maxLongNoDrop(const vector &Arr)
{
vector stackVec;
stackVec.push_back(-999999);//初始化第一个数为一个尽可能小的值
for (size_t i = 0; i < Arr.size(); i++)
{
if (Arr[i] > stackVec.back())//stackVec.back()该数组最前面的这个值
{
stackVec.push_back(Arr[i]);//将形成一个有序的数组
}
else
{
int mid = 0, low = 1, high = stackVec.size()-1;
//二分检索“数组栈”(有序的)中比当前Arr[i]大的第一个数的位置(为low)
while (low <= high)
{
mid = (low + high) / 2;
if (Arr[i] > stackVec[mid])
low = mid + 1;
else
high = mid - 1;
}
//替换之
stackVec[low] = Arr[i];
}
}
return (stackVec.size() - 1);
}
int main()
{
int n = 0;
while (cin>>n)
{
vector srcArr(n, 0);
for (size_t i = 0; i < n; i++)
cin >> srcArr[i];
cout << maxLongNoDrop(srcArr) << endl;
}
return 0;
}
又到毕业季,很多大公司来学校招聘,招聘会分散在不同时间段,小明想知道自己最多能完整的参加多少个招聘会(参加一个招聘会的时候不能中断或离开)。
第一行n,有n个招聘会,接下来n行每行两个整数表示起止时间,由从招聘会第一天0点开始的小时数表示。
n <= 1000 。
最多参加的招聘会个数。
3 9 10 10 20 8 15
2
#include "vector"
#include "string"
#include "algorithm"
#include
#include
using namespace std;
int GreedyActSelector(vector &s, vector &f);
int main()
{
int n = 0;
while (cin >> n&&n <= 1000)
{
vector vecstart(n);
vector vecend(n);
for (int i = 0; i < n; i++)
cin >> vecstart[i] >> vecend[i];
for (int i = 0; i < n; i++)
{
for (int j = i+1; j < n; j++)
{
if (vecend[i]>vecend[j])//对结束时间排序,由小到大
{
int temp1 = vecend[i];
vecend[i] = vecend[j];
vecend[j] = temp1;
int temp2 = vecstart[i];//开始时间也相应变换,但不一定有序
vecstart[i] = vecstart[j];
vecstart[j] = temp2;
}
}
}
cout << GreedyActSelector(vecstart, vecend) << endl;
}
return 0;
}
//以第一个招聘会作为起点(因为他是最早结束的,这样才可以尽可能增加多次活动的“潜力”),
//总是选择满足兼容条件下的最早结束的招聘会,因为这样可以使得剩下的时间资源可以更多的其他招聘会使用,
//这种选择方式一定可以选出最大兼容招聘会数。
int GreedyActSelector(vector &start, vector &finish)
{
int longlen = 0;
int k = 0;//记录最近加入的活动的下标
int count = 1;
for (int m = 1; m < start.size(); m++)
{
if (start[m] >= finish[k])//start[m]是下一个招聘会的开始时间,finish[k]是上一个招聘会的结速时间,我们总贪婪的找到下一个活动的开始时间比上一个的结束时间大
{
count++;
k = m;
}
}
return count;
}
测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( < 100 );随后的N(N-1)/2行对应村庄间的距离,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间的距离。为简单起见,村庄从1到N编号。
当N为0时,输入结束,该用例不被处理。
对每个测试用例,在1行里输出最小的公路总长度。
3 1 2 1 1 3 2 2 3 4 4 1 2 1 1 3 4 1 4 1 2 3 3 2 4 2 3 4 5 0
3 5
#include "vector"
#include "string"
#include "algorithm"
#include
#include "stack"
#include
#include
using namespace std;
class Edge
{
public:
int acity;//城市a
int bcity;//城市b
int cost; //建成a到b的路的花费
bool operator < (const Edge &q) const//注意返回值的类型,运算符重载。
{
return cost> n, n > 0)
{
int m = n*(n - 1) / 2;
UFSet uset(10000);
uset.makeSet(n);//初始化每个城市的祖先为自身
for (int i = 0; i < m; i++)
cin>> edge[i].acity>> edge[i].bcity>> edge[i].cost;
int mincost = uset.getMinCost(m);
cout << mincost << endl;
}
return 0;
}
3 1 2 1 0 1 3 2 0 2 3 4 0 3 1 2 1 0 1 3 2 0 2 3 4 1 3 1 2 1 0 1 3 2 1 2 3 4 1 0
3 1 0
#include "algorithm"
#include
#include "stack"
#include
#include
using namespace std;
class Edge
{
public:
int acity;//城市a
int bcity;//城市b
int cost; //建成a到b的路的花费
bool isBuild; //标记路是否建成
bool operator < (const Edge &q) const//注意返回值的类型,运算符重载。
{
return cost> n, n > 0)
{
int m = n*(n - 1) / 2;
UFSet uset(100);
uset.makeSet(n);//初始化每个城市的祖先为自身
for (int i = 0; i < m; i++)
{
cin>> edge[i].acity>> edge[i].bcity>> edge[i].cost>> edge[i].isBuild;
if (edge[i].isBuild == 1)
uset.unionSet(edge[i].acity, edge[i].bcity);//将已经建成的两个城市编号建立连接
}
int mincost = uset.getMinCost(m);
cout << mincost << endl;
}
return 0;
}
已知有面值为1元,2元,5元,10元,20元,50元,100元的货币若干(可认为无穷多),需支付价格为x的物品,并需要恰好支付,即没有找零产生。
求,至少需要几张货币才能完成支付。
如,若支付价格为12元的物品,最少需要一张10元和一张2元,即两张货币就可完成支付。
输入包含多组测试数据,每组仅包含一个整数p(1<=p<=100000000),为需支付的物品价格。
对于每组输入数据,输出仅一个整数,代表最少需要的货币张数。
10 11 13
1 2 3
#include
using namespace std;
int getAns(int key)
{//贪心选择的结果
if (key == 0)
return 0;
if (key == 8 || key == 9)
return 3;
else if (key == 1 || key == 2 || key == 5)
return 1;
else
return 2;
}
int main()
{
int n;
while (cin >> n)
{
int count=0;
count += n / 100;//计算百位及其以上
n = n % 100;//保留个位和十位
count += getAns(n / 10);//计算十位
count += getAns(n % 10);//计算个位
cout << count << endl;
}
return 0;
}
/**************************************************************
Problem: 1549
User: EbowTang
Language: C++
Result: Accepted
Time:50 ms
Memory:1520 kb
****************************************************************/
#include
#include "stack"
#include
#include
using namespace std;
const int money[] = { 100, 50, 20, 10, 5, 2, 1 };//注意这些面值能凑出任意正整数面值
int main()
{
int n;
while (cin >> n)
{
int count = 0;
for (int i = 0; i < 7; i++)
{
count += n / money[i];//总是贪心的选择面值大的
n = n%money[i];
}
cout << count << endl;
}
return 0;
}
/**************************************************************
Problem: 1549
User: EbowTang
Language: C++
Result: Accepted
Time:50 ms
Memory:1520 kb
****************************************************************/
【1】《算法导论》,第十六章,贪心算法
【2】《百度百科》
【3】《维基百科》
【4】http://www.cppblog.com/3522021224/archive/2007/06/16/26429.aspx
【5】https://en.wikipedia.org/wiki/Greedy_algorithm
【6】http://www.cnblogs.com/steven_oyj/archive/2010/05/22/1741375.html
【7】http://www.icodeguru.com/cpp/10book/