一,种树问题-贪心算法
Description
某条街被划为 n 条路段,这 n 条路段依次编号为 1…n。每个路段最多可以种一棵树。现在居民们给出了 h 组建议,每组建议包含三个整数 b,e,t 表示居民希望在路段 b 到 e之间至少要种 t 棵树。这些建议所给路段的区间可以交叉。请问:如果要满足所有居民的建议,至少要种多少棵树。
Input
第一行为 n,表示路段数。第二行为 h,表示建议数。 下面 h 行描述一条建议:b,e,t 用一个空格分隔。
Output
输出只有一个数,为满足所有居民的建议,所需要种树的最少数量。
思路
以样例为例,首先按右端点升序排序:要使种的树数目最少,实际是要使树尽可能的种在路段重复地段。类似于安排时间表的问题,用贪心算法处理。排好序后按照路段顺序遍历,并且每次从最右端点向左遍历该路段,即从最右端开始种树。这样可以实现最大限度的把树优先种在重复路段。
代码
-
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e6+7; struct tree { int b,e,t; }s[5010]; bool cmp(tree k,tree l) { return k.e<l.e; } int flag[90000]; int main() { int i,j,k,sum=0,n,h; scanf("%d%d",&n,&h); for(i=0;i<h;i++) {scanf("%d%d%d",&s[i].b,&s[i].e,&s[i].t); } sort(s,s+h,cmp); for(i=0;i<h;i++) { k=0; for(j=s[i].e;j>=s[i].b;j--) { if(flag[j]==1) k++; } if(k>=s[i].t) continue; for(j=s[i].e;j>=s[i].b;j--) { if(flag[j]==0) { flag[j]=1;k++;sum++; } if(k>=s[i].t) break; } } printf("%d\n",sum); return 0; }
二,括号匹配
1.Description
烤烤最近在一家数据公司实习。实习生嘛,被分配到的总是特别枯燥的任务,他的任务是对一串字符(不超过50个字符,可能包括括号、数字、字母、标点符号、空格)进行字符匹配的判断。
要求检查这一串字符中的( ) ,[ ],{ }是否匹配。做了一上午,烤烤眼睛都看花了,所以希望你来帮帮他 !
Input
输入数据有多组,每组数据不超过100个字符并含有( ,) ,[, ],{, }一个或多个。处理到文件结束。
Output
如果匹配就输出“yes”,不匹配输出“no”
2. 解析
碰上左边括号压入栈,碰上右边括号则判断:
a. 此时栈内是否有元素(注意这个要放在第一个判断,之后代码会详解)
b. 栈顶元素是否与其配对
若两个条件都满足则把左括号压出,继续判断下一个;若不满足则结束判断,返回“False”。
最后字符数组所有元素判断完后,再次判断栈内是否有元素。
a. 若有元素,则该元素定是未匹配的,返回“False”;
b. 若无元素,则此次括号匹配判断成功。
3. 代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+7;
bool cmp(char a,char b)
{
return a=='['&&b==']'||a=='('&&b==')'||a=='{'&&b=='}';
}
int main()
{
char a[200];
int i,j,k,len,sum,t,flag;
while(gets(a))
{
stack<char>s;
flag=1;
len=strlen(a);
for(i=0;i<len;i++)
{
if(a[i]=='['||a[i]=='{'||a[i]=='(')
s.push(a[i]);
else if(a[i]==']'||a[i]=='}'||a[i]==')')
{
if(!s.empty()&&cmp(s.top(),a[i]))
s.pop();
else
{
printf("no\n");
flag=0;break;
}
}
}
if(flag)
{
if(s.empty())
printf("yes\n");
else
printf("no\n");
}
}
return 0;
}