【备战蓝桥杯】USACO--> Milking Cows[2]

来源:互联网 发布:png编辑软件 编辑:程序博客网 时间:2024/06/06 02:46

题目网址:http://wikioi.com/problem/1385/

昨天由于家里有点事情,就没有继续忙了。其实昨天上午已经按照我自己的思路把代码写出来了。可惜结果总有两个不能ac了。

后来参考了相关思路,发现自己思考问题的时候,太过拘谨。不过也可以理解,因为我本身对排序算法就不是很熟悉,总觉得像快速排序里面有递归调用就会很慢。

其实不是这样。后来写出的算法,明显比自己之前想象的算法要快一倍,而且思路清晰,容易调试。

果然,到了真正比赛的时候,还是写思路清晰的算法比较好。一是好调试错误。二是未必会慢。

这个是我自己设想的算法,一个是实现起来繁琐。情况复杂。前后融合都要考虑,二是,写到后面发现,还是要借助排序。因为再不排序,又会复杂,成指数级= =。

/*300---------1000         700-------1200                   1500---------2100                                      2000 27001、第一个组合与所有匹配,能融合,就融合,并标记融合过的;2、产生的新组合与剩下的未标记的融合,同上;3、该组合不能再融合时,从下一个未标记的开始搜索融合;4、下一个标记的不能融合时候,再下一个;5、所有都标记上了,结束。选出最长时间与最短时间 */#include <stdio.h>#include <stdlib.h>typedef struct _NODE{int beg;int end;}NODE;//0,右边融合;1,左边融合;2,中间,不用理会;-1,不相交 int check(NODE i1,NODE i2){if( i2.beg >= i1.beg && i2.beg <= i1.end && i2.end > i1.end )return 0;else if( i2.end >= i1.beg && i2.end <= i1.end && i2.beg < i1.beg  )return 1;else if( i2.beg >= i1.beg&& i2.end<= i1.end)return 2;elsereturn -1;}void quick_sort(NODE *node,int l,int r){ if (l < r)      {          //Swap(s[l], s[(l + r) / 2]); //将中间的这个数和第一个数交换 参见注1          int i = l, j = r;NODE x = node[l];          while (i < j)          {              while(i < j && node[j].beg >= x.beg) // 从右向左找第一个小于x的数                  j--;                if(i < j)                   node[i++] = node[j];                            while(i < j && node[i].beg < x.beg) // 从左向右找第一个大于等于x的数                  i++;                if(i < j)                   node[j--] = node[i];          }          node[i] = x;          quick_sort(node, l, i - 1); // 递归调用           quick_sort(node, i + 1, r);      }}int main(){int n;scanf("%d",&n);int i;NODE *input = (NODE *)malloc(sizeof(NODE) * n);int *flag = (int *)malloc(sizeof(int) * n);for(i=0 ; i< n; i++){//0 未标记 ;1已经融合过; 2加工过 flag[i] = 0;scanf("%d %d",&input[i].beg,&input[i].end);}flag[0] = 2;int isAdd = 0;int j=0;int status;int cou=1;while(1){for( i=j+1 ; i< n ; i++){if( flag[i]==0){status = check(input[j],input[i]);if( status==0){input[j].end= input[i].end;isAdd = 1;flag[i]=1;}else if( status==1){input[j].beg= input[i].beg;isAdd = 1;flag[i]=1;}else if(status==2 ){flag[i]=1;}}}//当融合到无法融合的时候,寻找下一个 if( isAdd == 0){for(i=j ; i < n && flag[i]!=0; i++);//全被标记,结束寻找 if( i==n){break;} j = i; flag[j] = 2; cou++;}isAdd = 0;}int max_ji = 0,max_meiji = 0;NODE *getMax = (NODE *)malloc(sizeof(NODE) * cou);//筛选出最终的时间组合,并找出最大挤奶时间 for(i=0,j=0 ; i < n; i++){if(flag[i] ==2){getMax[j++] = input[i];max_ji = (input[i].end-input[i].beg) > max_ji ? (input[i].end-input[i].beg) : max_ji;}}//排序先 quick_sort(getMax,0, cou-1);//筛选最大不挤奶时间 for(i=0 ; i< cou-1 ; i++){max_meiji = (getMax[i+1].beg- getMax[i].end)>max_meiji ?(getMax[i+1].beg- getMax[i].end):max_meiji;}printf("%d %d",max_ji,max_meiji);return 0;}
这个是后来根据参考,自己纠正的算法,首先把排序做了。用快排,然后思路就瞬间清晰了。

其实,本训练的目的,就是掌握不同问题的解决思路,在每个问题解决的时候,学会使用其中应当明白的算法。

自然,解法还是有很多的。但是要以题目本身的目的来围绕着学习。

像本类题目的目的,就是写出容易理解的枚举算法。或者通过一定的优化手段,再来枚举。之前一直没想通这个怎么优化。原来就是利用我一直不熟悉的排序算法。

看来之后还要好好补补排序算法了。先把快排弄好吓,快速理解。

#include <stdio.h>#include <stdlib.h>typedef struct _NODE{int beg;int end;}NODE;void quick_sort(NODE *node,int l,int r){ if (l < r)      {          //Swap(s[l], s[(l + r) / 2]); //将中间的这个数和第一个数交换 参见注1          int i = l, j = r;NODE x = node[l];          while (i < j)          {              while(i < j && node[j].beg >= x.beg) // 从右向左找第一个小于x的数                  j--;                if(i < j)                   node[i++] = node[j];                            while(i < j && node[i].beg < x.beg) // 从左向右找第一个大于等于x的数                  i++;                if(i < j)                   node[j--] = node[i];          }          node[i] = x;          quick_sort(node, l, i - 1); // 递归调用           quick_sort(node, i + 1, r);      }}int main(){int n;scanf("%d",&n);NODE *input = (NODE *)malloc(sizeof(NODE) *n);int i;for(i=0 ; i < n; i++){scanf("%d %d",&input[i].beg,&input[i].end);}//通过排序的方法,就解决了情况复杂多变的情况。//本题的核心,就是用排序的方法,简化线段离散化的情况,//使得问题分析变得简单。 quick_sort(input,0,n-1);int max_continus=0,max_idle=0;int max_beg=  input[0].beg,max_end = input[0].end;for(i=1 ; i< n ; i++){//下一个线段的beg在前一个线段内部,下一个线段将被吸收,取两者最大的end if( input[i].beg <= max_end){max_end = input[i].end>max_end ? input[i].end:max_end;}//反之,将开始另外一段线段的比较。 else {max_continus = (max_end-max_beg)>max_continus ? (max_end-max_beg):max_continus;max_idle = (input[i].beg - max_end)> max_idle ?(input[i].beg - max_end): max_idle;max_beg = input[i].beg;max_end = input[i].end;}}//竟然忽略了最后要把结果再次比较一下。嘿哈。浪费了我20分钟。 max_continus = (max_end-max_beg)>max_continus ? (max_end-max_beg):max_continus;max_idle = (input[i].beg - max_end)> max_idle ?(input[i].beg - max_end): max_idle;printf("%d %d",max_continus,max_idle);return 0;}


0 0
原创粉丝点击