c语言算法优化

Python014

c语言算法优化,第1张

【算法描述】

转某牛人的解题报告!!!!

这道题在没看数据规模之前以为是一道简单的DP,但是数据开到十亿,无论在时间还是空间复杂度都过大,所以就要进行优化了。

解一:

简单方法:预期得分30。简单动态规划,f[i]代表青蛙跳到i点时所可能踩到的最少石子数,所以有f[i]=min{f[k]+map[i]}(i-s≤k≤i-t),其中map[i]代表i上是否有石子,有是1,否则0。算法复杂度O(n^2)。

解二:

改进方法:预期得分100。我们会发现,虽然桥很长,但上面最多只有100个石子,想到能否用石子DP,而应该是不行的。那能否基于第一种方法?由于石子排布非常的疏,我们还会发现,如果两个石子相隔甚远,那他们中间的f[i]大部分将会是同一个数,能否把两个石子的距离缩短,使之还与原来等效?要是行的话怎么缩?王乃岩同学考试时做了一个方法能够过全部数据,用的滚动数组存储,下面列出了他的程序。我自己也写了个程序,和他不尽相同:我令L=stone[i]-stone[i-1](stone[i]代表按坐标由小到大顺序排列的石块坐标),当L能够被t整除时(L%t==0),令k=t;当L不能被t整除时(L%t!=0),令k=L%t。然后令k为k+t,最后判断如果k>L,那么map[]数组中stone[i]和stone[i-1]两石头的距离就被等效成为L(也就是没变);如果k<=L,那么map[]数组中stone[i]和stone[i-1]两石头的距离就被等效成为k,可以看出来,这样处理完,两石子最大间距为2*t,大大的缩短了数组,再按解一进行DP,就可以通过了。

#include <stdio.h>

#include <string.h>

long stone[101]

int map[100001]

int f[100001]

long L

int S, T, M

void quickSort(int l, int r)

{

int i , j

long temp

i = l

j = r

temp = stone[i]

while (i <j)

{

while (i <j &&stone[j] >temp)

j--

if (i <j)

{

stone[i] = stone[j]

i++

}

while (i <j &&stone[i] <temp)

i++

if (i <j)

{

stone[j] = stone[i]

j--

}

}

stone[i] = temp

if (i - 1 >l) quickSort(l, i - 1)

if (i + 1 <r) quickSort(i + 1, r)

}

int main()

{

int i, j

long l, k, p = 0, min

scanf("%ld%d%d%d", &L, &S, &T, &M)

for (i = 1i <= Mi++)

scanf("%ld", &stone[i])

memset(map, 0, sizeof(int)*100001)

memset(f, 0, sizeof(int)*100001)

quickSort(1, M)

stone[0] = 0

p = 0

for (i = 1i <= Mi++)

{

l = stone[i] - stone[i - 1]

if (l % T == 0)

k = T

else

k = l % T

k = k + T

if (l <k)

k = l

p = p + k

map[p] = 1

}

for (i = 1i <= p + Ti++)

{

min = 1000

for (j = i - Tj <= i - Sj++)

if ( j >= 0 &&f[j] <min)

min = f[j]

f[i] = min + map[i]

}

min = 1000

for (i = p + 1i <= p + Ti++)

if (f[i] <min)

min = f[i]

printf("%d\n", min)

return 0

}

1、所有m个数据读入之后再一起统一排序,可以调用qsort或者自己写简单的冒泡,10万个以内应该很快的。

2、查询采用折半法,找到一个之后往前往后看看有多少个相同的。(或者先对步骤1的结果进行归并,然后再折半查询。具体看q的数量,如果不大的话就用前一种直接查,如果q和m相近也很大的,那么采用后一种。)

试试这个——

void main(void){

int n,a,b,c[15],i,count=0,j

scanf("%d",&n)

for(i=0i<ni++)

scanf("%d",&c[i])

scanf("%d%d",&a,&b)

for(i=ai%8i++)

for(i<=bi+=8){

for(j=0j<nj++)

if(i%c[j]==0)

break

if(j==n)

count++

}

printf("%d\n",count)

}