• 【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;
    }
    


  • 相关阅读:
    【网页前端】JS呈现时间戳为与当前时间比较结果
    【Django工具】Django_debug_toolbar使用
    【Django Models】Django数据查询 汇聚
    【Django Models】虚拟化提取Models公共的功能
    【网页在线编辑】图文发送的模式
    【Django后台数据管理】后台数据新建或者保存,经常遇到提示This field is required
    【BBS】Discuz部署
    【Django】QuerySet的分页和排序
    【Django数据库】如何将一个表自定义的key列还原成id列作为key
    18.6
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793864.html
Copyright © 2020-2023  润新知