有效地计算线段

时间:2014-07-30 05:14:38

标签: c++ algorithm math

我正在尝试从澳大利亚信息学培训网站解决Slicing Paradise。这个想法是你有一系列的块(实际上是语句中的林,我的代码中是land),并且每次都会删除一个块(或转换为一个度假区),这可能会增加或减少连续(森林)块的运行次数。我要计算历史最大次数。输入是块数N,接着是N行,给出每个块的移除时间。时间是从1开始的连续整数。

我的代码工作正常(我认为),但对于一些较大的案例来说,它太慢了。有人可以建议一个简单的快速工作解决方案,或者可以对我的任何改进使其在O(N)中运行吗?

慢速解决方案

#include <cstdio>

FILE* infile;
FILE* outfile;
int N,c,j,l,best;

int main(){
    infile=fopen("slicein.txt","r");
    outfile=fopen("sliceout.txt","w");

    fscanf(infile,"%d\n",&N);

    int land[N+1];
    int location[N+1];

    for (int i=1;i<=N;i++){
        fscanf(infile,"%d\n",&location[i]);
        land[i]=0;
    }

    j=1;l=1;c=1;

    for (int i=1;i<=N;i++){
        if (location[i]==j){
            land[i]=1;
            if (land[i+1]!=1 && land[i-1]!=1 && i!=N && i!=1) c++;
            else if (land[i-1]==1 && land[i+1]==1 && i!=N && i!=1) c--;
            j++;
            if (c>best) best=c;
            i=0;
        }
        if (i==N && l!=N*N){
            i=0;
        }
        else if (l==N*N) break;
        l++;
    }

    fprintf(outfile,"%d\n",best);

    fclose(infile);
    fclose(outfile);

    return 0;
}

3 个答案:

答案 0 :(得分:3)

你的问题是你基本上有两个嵌套循环,一个用于j,另一个用于i,尽管你并没有明确地写出来。这为您提供了一种O(N)方法来查找当前位置,这相当于O(N 2 )总成本。

基本信息是,在每轮j中,您需要找到在该轮中转换的位置i。您可以在阅读输入时为其构建地图。而不是将location作为地图从一个位置到另一个时间,使其成为一个时间到位置的地图:

for (int i=1;i<=N;i++){
    int t;
    fscanf(infile,"%d\n",&t);
    location[t] = i;
    land[i]=0;
}

然后你可以用一个O(N)循环来做,一切都应该没问题。确保索引正确,因为您似乎在某些地方使用基于索引的索引,而在其他地方使用基于零的索引。

答案 1 :(得分:0)

无法找出您的解决方案,但以下是 O(nlogn)中执行该算法的算法: -

  
      
  1. 在矢量
  2. 中存储tupples(i,time [i])   
  3. 根据时间[i]
  4. 对矢量进行排序   
  5. 维护一个布尔数组以检查是否采用了绘图。
  6.   
  7. 最初的所有 = false
  8.   
  9. 按排序顺序开始构建绘图。
  10.   
  11. 最初的森林= 1
  12.   
  13. 构建绘图时,检查布尔数组中的相邻绘图。
  14.   
  15. 如果两者都被占用那么森林=森林 - 1
  16.   
  17. 如果一个人被占用则没有变化
  18.   
  19. 如果两者都是空森林=森林+ 1
  20.   
  21. 每次施工后检查森林ID是否大于最大值。
  22.   

时间复杂度: -

Sorting takes O(logn)
plot construction in sorted order O(n)

答案 2 :(得分:0)

对于任何对此感兴趣的人,我的回答是:

#include <cstdio>

FILE* infile;
FILE* outfile;
int N,c,j,l,b,best;

int main(){
infile=fopen("slicein.txt","r");
outfile=fopen("sliceout.txt","w");

fscanf(infile,"%d\n",&N);

int land[N+1];
int location[N+1];
j=1;l=1;c=1;b=1;

for (int i=1;i<=N;i++){
    int t;
    fscanf(infile,"%d\n",&t);
    location[t]=i;
    land[i]=0;
}
for (int i=1;i<=N;i++){
    land[location[i]]=1;
    if (land[location[i]-1]!=1 && land[location[i]+1]!=1 && location[i]!=1 && location[i]!=N) c++;
    else if (land[location[i]-1]==1 && land[location[i]+1]==1 && location[i]!=1 && location[i]!=N) c--;
    else if (land[location[i]-1]==1 && location[i]==N) c--;
    else if (land[location[i]+1]==1 && location[i]==1) c--;
    if (c>best) best=c;
}

fprintf(outfile,"%d\n",best);

fclose(infile);
fclose(outfile);

return 0;}

感谢MvG建议算法:)