数据结构树/堆(优先队列)做题:1336:找树根和孩子;单词查找树;1338:医院设置;1369:合并果子;1373:鱼塘钓鱼;1372:小明的账单

1336:【例3-1】找树根和孩子

#include
using namespace std;
int main(){
	int n,m,x,y,root,maxnode,maxn=0,cnt=0;
	int tree[105];
	memset(tree,0,sizeof(tree));
	cin>>n>>m;
	
	for(int i=1;i<=m;i++){
		cin>>x>>y;
		tree[y]=x;
	}  
	for(int i=1;i<=n;i++){
		if(tree[i]==0){
			root=i;
			break;
		}
	}
	for(int i=1;i<=n;i++){
		cnt=0;
		for(int j=1;j<=n;j++){
			if(tree[j]==i){
				cnt++;
			}
		}
		if(cnt>maxn){
			maxn=cnt;
			maxnode=i;
		}
	}
	cout<

单词查找树

和哈夫曼编码有什么关系呢???

//我也不知道为什么它这样建树就是节点数最少呀!!! 
#include
using namespace std;
string a[10000];
string s;
int n; 
int main(){
	while(cin>>a[++n]);
	sort(a+1,a+1+n);
	int t=a[1].length();
	for(int i=2;i<=n;i++){
		int j=0;
		while(a[i][j]==a[i-1][j]&&j

1338:【例3-3】医院设置

思路:

这是一道简单的二叉树应用问题,问题中的节点数并不多,数据规模也不大,采用邻接矩阵存储,用Floyed求出任意两节点之间的最短路径,然后穷举医院可能建立的n个节点位置找出一个最小距离的位置即可。

其实就是用floyed求一遍多源最短路(任意两点之间的最短路径),然后枚举直接求建立在每一点医院时的耗散值。

学到的东西:

书上说,这类题是树的中心点问题,本来我还想枚举每个点为起点然后用树的遍历来求耗散值呢,看来还是用最短路更简单。

#include
#include
using namespace std;
const int maxn=0x3f3f3f3f;
int a[101];
int g[101][101];
int main()
{
    int n;
    cin>>n;
    int l,r;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        g[i][j]=maxn;
    for(int i=1;i<=n;i++)
    {
        g[i][i]=0;
        cin>>a[i]>>l>>r;
        if(l>0) g[i][l]=g[l][i]=1;
        if(r>0) g[i][r]=g[r][i]=1;
    }
    for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
        }
    int minn=maxn;
    int sum=0;
    for(int i=1;i<=n;i++)
    {
        sum=0;
        for(int j=1;j<=n;j++)
        {
            sum+=g[i][j]*a[j];
 
        }
        if(sum

1369:合并果子(fruit)

思路:

数据结构树/堆(优先队列)做题:1336:找树根和孩子;单词查找树;1338:医院设置;1369:合并果子;1373:鱼塘钓鱼;1372:小明的账单_第1张图片

代码:

stl版(CV一本通)和非stl版都在下面。 

(priority_queue做题时的的用法:传送门。)

/*
#include
int tot;
int tree[20001];
void up(int x)
{
	if (x==1) return;
	int y=x>>1;
	if (tree[x]tree[y+1]) y++;
	if (y<=tot&&tree[y]
using namespace std;
int n;
priority_queue,greater >qu;//小根堆优先队列
void work(){
	cin>>n;
	int ans=0,x,t1,t2;
	for(int i=1;i<=n;i++){
		cin>>x;
		qu.push(x);
	}
	for(int i=1;i

1373:鱼塘钓鱼(fishing)

题意:

就补充一点:如果没在一个鱼塘钓过鱼的话,那那个鱼塘的每分钟收益不变。只有一直在某个鱼塘钓鱼,那个鱼塘的收益才会减少。

假设能钓到鱼的数量仅和已钓鱼的次数有关,且每次钓鱼的时间都是整数分钟。 

思路:

假设最后是在第k个鱼塘捕鱼的(因为路上会花费时间,所以只经过中间的鱼塘一次),那路上的这段时间就确定了,剩下的时间是捕鱼的时间。对前K个鱼塘,每次选捕鱼次数最多的鱼塘。枚举K。 

代码:

又是CV这个代码好强呀。

https://blog.csdn.net/Wchenchen0/article/details/81259412

#include
#define fish first
#define lake second
using namespace std;
priority_queue >heap;
int f[105];//每个鱼塘鱼的数量 
int t[105];//到达下一个鱼塘的时间 
int d[105];//鱼塘里的鱼随时间减少的数量 
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++) cin>>f[i];
    for(int i=1;i<=n;i++) cin>>d[i];
    for(int i=1;i>t[i];
    int m;
    cin>>m;
    int T=0;
    int t1=0;
    int ans=0;
    int maxn=0;
    for(int k=1;k<=n;k++){//枚举最远走到的池塘的编号
        T=m-t1;//计算剩余的时间
        ans=0;
        while(!heap.empty()){//清空堆 
            heap.pop();
        }
        for(int i=1;i<=k;i++){//收集能够钓鱼的池塘治疗
            heap.push(make_pair(f[i],i));
        }
        while(T>0&&heap.top().fish>0){
            paira=heap.top();
            heap.pop();
            ans+=a.fish;//贪心取鱼最多的池塘
            a.fish-=d[a.lake];//修改鱼的数量
            heap.push(a);//维护堆
            T--;//剩余时间变少
        }
        if(ans>maxn) maxn=ans;//刷新最优解
        t1+=t[k];//累计走路需要的时间
 
    }
    cout<

1372:小明的账单

代码一:

代码一有问题(只能通过前五个测试,其余的是运行错误,我寻思数组也没溢出呀,可能是优先队列有问题??),有同样思路且通过的大佬看出问题的话可以点拨下。 

思路:

把输入的每个数字定一个编号,用vis数组记录输出过的数字。用两个堆,分别记录最大值和最小值,每次输出堆顶元素,vis标记过的就不输出了。

#include
using namespace std;
struct cmpDa{
	bool operator()(pair a,pair b){
		return a.first a,pair b){
		return a.first>b.first; 
	}
};
priority_queue,vector >, cmpDa> queDa;
priority_queue,vector >, cmpXiao> queXiao;
int n,vis[100100];
int main(){
	ios::sync_with_stdio(false);
	cin>>n;
	int m,cnt=0,tmp;
	for(int i=1;i<=n;i++){
		cin>>m;
		for(int j=1;j<=m;j++){
			cin>>tmp;
			cnt++;
			queDa.push(make_pair(tmp,cnt));
			queXiao.push(make_pair(tmp,cnt));
		}
		int t1=queXiao.top().second;
		while(vis[t1]){
			queXiao.pop();
			t1=queXiao.top().second;
		}
		cout<

代码二: 

#include
#include
#include
using namespace std;
multiset st;
 
int main(){
	int n;
	scanf("%d",&n);	//用cin cout会爆
	for (int i=1,m; i<=n; i++){	//枚举每天
		scanf("%d",&m);
		for (int j=1,x; j<=m; j++){
			scanf("%d",&x);
			st.insert(x);	//输入
		}
		printf("%d ",*st.begin());	//输出最小值
		st.erase(st.begin());	//删除最小值
		printf("%d\n",*(--st.end()));	//输出最大值
		st.erase(--st.end());		//删除最大值
	}
	return 0;
}

1371:看病

时间超限了。

#include
using namespace std;
struct cmp{
	bool operator()(pair a,pair b){
		return a.second, vector >, cmp > que;
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0); 
	int n;
	cin>>n;
	string op,name;
	int tmp;
	for(int i=1;i<=n;i++){
		cin>>op;
		if(op=="push"){
			cin>>name>>tmp;
			que.push(make_pair(name,tmp));
		}else{
			if(que.empty()){
				cout<<"none\n";
				continue;
			}
			pair tt=que.top();
			que.pop();
			cout<

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(ACM算法)