zoukankan      html  css  js  c++  java
  • 【NOIP2005提高组T2】过河-DP+路径压缩

    测试地址:过河

    做法:30分的做法很容易想,设f[i]为走到i时所踩的最少的石子数,则状态转移方程为:f[i]=f[i-x](i处无石子)或f[i-x]+1(i处有石子),其中S≤x≤T。但是L高达10亿,我们就要想办法优化。

    首先是空间上的,由于我们在状态转移方程中只用到了f[i-S]到f[i-T],所以使用滚动数组即可。

    然后是时间上的,我们知道,虽然L很大,但是石子的数目M很小,这样就会产生一种情况:如果两个石子中间有很大一块空白,那么就会浪费很多时间,因为在这期间最少石子数都不会变。在上述的滚动数组定义下,就表现为:对于所有的下标,f[]的值相同。一旦出现这种情况,只要下一步没有石子,f[]的值都不变,所以我们可以直接跳到下一个石子所在的地方进行计算。注意,上述性质在S=T的时候不成立,特判一下即可。

    另外还需要注意,输入数据中给的石子位置是乱序,需要先排序。

    以下是本人代码:

    #include <cstdio>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #define inf 999999999
    using namespace std;
    int l,s,t,m,f[15]={0};
    int pos[110]={0};
    
    int main()
    {
      scanf("%d",&l);
      scanf("%d%d%d",&s,&t,&m);
      for(int i=1;i<=m;i++)
        scanf("%d",&pos[i]);
      pos[0]=0;pos[m+1]=0;
      
      if (s!=t)
      {
        sort(pos+1,pos+m+1,less<int>());
    	int i=s,p=1;
    	int last=101,cnt=0;
    	f[0]=0;
    	for(int j=1;j<t;j++) f[j]=101;
    	while(i<=l+t)
    	{
    	  if (i==pos[p]) f[i%t]++;
    	  for(int j=t;j>=s;j--) f[i%t]=min(f[i%t],f[(i-j+t)%t]+(i==pos[p]));
    	  if (i>=pos[p]&&p<=m) p++;
    	  if (f[i%t]==last) cnt++;
    	  else
    	  {
    	    last=f[i%t];
    		cnt=1;
    	  }
    	  i++;
    	  if (cnt>t&&i<l)
    	  {
    	    if (p<=m) i=pos[p];
    		else i=l;
    		cnt=0;
    	  }
    	}
    	int ans=inf;
    	for(int j=0;j<t;j++)
    	  ans=min(ans,f[j]);
    	printf("%d",ans);
      }
      else
      {
        int ans=0;
    	for(int i=1;i<=m;i++)
    	  if (pos[i]%s==0) ans++;
    	printf("%d",ans);
      }
      
      return 0;
    }
    


  • 相关阅读:
    POJ 1953 World Cup Noise
    POJ 1995 Raising Modulo Numbers (快速幂取余)
    poj 1256 Anagram
    POJ 1218 THE DRUNK JAILER
    POJ 1316 Self Numbers
    POJ 1663 Number Steps
    POJ 1664 放苹果
    如何查看DIV被设置什么CSS样式
    独行DIV自适应宽度布局CSS实例与扩大应用范围
    python 从入门到精通教程一:[1]Hello,world!
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793863.html
Copyright © 2011-2022 走看看