POJ3614

xiaoxiao2021-02-27  500

/* POJ 3614 用快速排序会更快 这儿用的选择排序 奶牛美容:有C头奶牛日光浴,每头奶牛分别需要mini和maxi单位强度之间的阳光。 现有L种防晒霜,分别能使阳光强度稳定为SPF_i,其瓶数为cover_i。求最多满足多少头奶牛 个人理解:好奇葩的题目 奶牛的毛白长了^!^ 一共C头牛 第i头牛 需要的阳光强度 ∈[mini,maxi] 有L种防晒霜 第i瓶能让阳光强度稳定在SPFi 且第i种有coveri瓶 问 最多能满足多少头牛 假设第i种防晒霜 对于这瓶防晒霜 可能会有多头牛 能适合即 SPFi ∈[mini,maxi] 那么这瓶最好给谁呢? 当然是给maxi小的牛 因为 maxi大的牛可能别的防晒霜也适合 即它的选择的空间大 即: 在满足minSPF的条件下,尽量把SPF小的防晒霜用在maxSPF小的奶牛身上, 因为maxSPF大的奶牛有更大的选择空间。用一个最小堆来维护 将奶牛按照阳光强度的最小值从小到大排序。 将防晒霜也按照能固定的阳光强度从小到大排序 从最小的防晒霜枚举,将所有符合 最小值小于等于该防晒霜的 奶牛的 最大值 放入最小堆之中。 然后堆中最小值先出 就可以将这些最大值中的最小的取出来。更新答案。 */ # include <stdio.h> # define N 2500 void insert(int Tree[],int X);//最小堆 向Tree堆里插入X tree[0]用来记录当前堆中数的个数 int DelMin(int Tree[]);//最小堆 删除最小值 tree[0]用来记录当前堆中数的个数 void paixu(int A[][N],int n);//以A[0]为比较依据 升序 void change(int *A,int *B);//交换A B的值 int main(){ int C,L,i,num=0,SUM=0,maxSPF; int COW[2][N]={0},LFS[2][N]={0},tree[N]={0}; scanf("%d %d",&C,&L); for(i=0;i<C;i++) scanf("%d %d ",&COW[0][i],&COW[1][i]);//&COW[0][i],&COW[1][i] 分别存储牛的min max光 for(i=0;i<L;i++) scanf("%d %d ",&LFS[0][i],&LFS[1][i]);//LFS[0] LFS[1]分别存储防晒霜的 SPF 与瓶数 paixu(COW,C);//按照牛的mini生序 paixu(LFS,L);//按照化妆品的SPF升序 for (i=0;i<L;i++) { //num为当前选中的满足可以涂防晒霜的牛 while (num<C&&COW[0][num]<=LFS[0][i])//选出符合第i瓶防晒霜的牛 insert(tree,COW[1][num++]);//进堆 while (tree[0]&&LFS[1][i]) { if (DelMin(tree)>=LFS[0][i])// “maxi”比这一瓶的上限大,说明这头奶牛可以被涂上防晒霜 { ++SUM; --LFS[1][i]; } } } printf("%d\n",SUM); return 0; } void insert(int Tree[],int X)//向Tree堆里插入X { int par,i=++Tree[0]; //插入X 后 Tree[0]+1 while(i>1) //直到i不是根节点 { par=i/2; //父节点为par if(Tree[par]<=X) break;//如果父节点满足最大堆的特性 则插入当前的位置即可 Tree[i]=Tree[par]; //否则调整堆 即位置上移 i=par; } Tree[i]=X;//插入新节点 } int DelMin(int Tree[])//删除最小值 { int i=1,root=Tree[1],R,L,X=Tree[Tree[0]--];//X记录当前末尾节点 root为根 即为最小值 if(Tree[0]<0) return -1; while(i*2<=Tree[0]) { L=i*2; R=L+1;//Left Right 记录左右节点 if(R<=Tree[0]&&Tree[R]<Tree[L])L=R; if(Tree[L]>=X) break;//如果所有的位置已经调整好 跳出循环 Tree[i]=Tree[L];//否则继续调整堆 i=L; } Tree[i]=X; return root; } void paixu(int A[][N],int n)//以A[0]为比较依据 升序 { int i,j,k; for(i=0;i<n-1;i++) { k=i; for(j=i+1;j<n;j++) if(A[0][j]<A[0][k]) k=j; if(k!=i) { change(&A[0][i],&A[0][k]); change(&A[1][i],&A[1][k]); } } } void change(int *A,int *B)//交换A B的值 { int C=*A; *A=*B; *B=C; } Problem: 3614 User: aust182015302974Memory: 232K Time: 0MSLanguage: C Result: Accepted # include <stdio.h> # define N 2500 # define WEI 2 int C,L,i,num,SUM; int COW[2][N],LFS[2][N]; int tree[N],Tree[2][N]; void INSERT(int Tree[][N],int S[]); void DELMIN(int Tree[][N]);//删除最值 将最值存在S中 void insert(int Tree[],int X)//向最小堆中插入X { int par,i=++Tree[0]; //插入X 后 Tree[0]+1 while(i>1) //直到i不是根节点 { par=(i>>1); //父节点为par if(Tree[par]<=X) break; //将<=改为>=即改为最大堆了 Tree[i]=Tree[par]; //否则调整堆 即位置上移 i=par; } Tree[i]=X; //插入新节点 } int Delmin(int Tree[]) { int i=1,L=2,root=Tree[1],X=Tree[Tree[0]--]; while(L<=Tree[0]) { L+=L<Tree[0]&&Tree[L+1]<Tree[L]; if(Tree[L]>=X) break; Tree[i]=Tree[L]; i=L; L=i<<1; } Tree[i]=X; return root; } int main(){ int T[2]; scanf("%d %d",&C,&L); for(i=0;i<C;i++) { scanf("%d %d",&T[0],&T[1]); INSERT(Tree,T); } i=0; while(Tree[0][0]) { COW[0][i]=Tree[0][1]; COW[1][i++]=Tree[1][1]; DELMIN(Tree); } for(i=0;i<L;i++) { scanf("%d %d",&T[0],&T[1]); INSERT(Tree,T); } i=0; while(Tree[0][0]) { LFS[0][i]=Tree[0][1]; LFS[1][i++]=Tree[1][1]; DELMIN(Tree); } for (i=0;i<L;i++) { while (num<C&&COW[0][num]<=LFS[0][i]) insert(tree,COW[1][num++]); while (tree[0]&&LFS[1][i]) { if (Delmin(tree)>=LFS[0][i]) { ++SUM; --LFS[1][i]; } } } printf("%d\n",SUM); return 0; } void INSERT(int Tree[][N],int S[]) //向最小堆Tree[]里插入元素S[WEI] { int par,i=++Tree[0][0],j; //插入X 后 Tree[0]+1 while(i>1) //直到i不是根节点 { par=(i>>1); //父节点为par if(Tree[0][par]<=S[0]) break;//如果父节点满足堆的特性 则插入当前的位置即可 for(j=0;j<WEI;j++) //如果将Tree[0][par]<=S[0]改为Tree[0][par]>=S[0] 即为最大堆插入方式 Tree[j][i]=Tree[j][par]; //否则调整堆 即位置上移 i=par; } for(j=0;j<WEI;j++) Tree[j][i]=S[j]; } void DELMIN(int Tree[][N])//删除最值 将最值存在S中 { int i=1,j,R,L=2,m=Tree[0][0]--,T[WEI]; for(j=0;j<WEI;j++) T[j]=Tree[j][m]; while(L<m) { L+= L<Tree[0][0]&&Tree[0][L+1]<Tree[0][L]; if(Tree[0][L]>=T[0]) break;//并将 Tree[0][L]>=T[0]改为Tree[0][L]<=T[0]即为最大堆的删除代码 for(j=0;j<WEI;j++) Tree[j][i]=Tree[j][L];//否则继续调整堆 i=L; L=i<<1; } for(j=0;j<WEI;j++) Tree[j][i]=T[j]; //调整好并赋值 }
转载请注明原文地址: https://www.6miu.com/read-753.html

最新回复(0)