usaco Postal Vans(dp)

来源:互联网 发布:mac使命召唤7不足5m 编辑:程序博客网 时间:2024/04/30 03:45

是哈密顿回路,然后。。。就不知道怎么写了 ,以前写过类似的不过情况没这么多也没这么复

 

usaco training 6.1.1 Postal Vans 题解

标签: usaco training题解dp
 1511人阅读 评论(0) 收藏 举报
 分类:

目录(?)[+]

转载请注明出处:http://blog.csdn.net/jiangshibiao/article/details/21446033

【原题】

Postal Vans

ACM South Pacific Region -- 2003

Tiring of their idyllic fields, the cows have moved to a new suburb. The suburb is a rectangular grid of streets with a post office at its Northwest corner. It has four avenues running East-West and N (1 <= N <= 1000) streets running North-South.

For example, the following diagram shows such a suburb with N=5 streets, with the avenues depicted as horizontal lines, and the post office as a dark blob at the top-left corner:

Each day the postal van leaves the post office, drives around the suburb and returns to the post office, passing exactly once through every intersection (including those on borders or corners). The executives from the post company want to know how many distinct routes can be established for the postal van (of course, the route direction is significant in this count).

For example, the following diagrams show two such routes for the above suburb:

As another example, the following diagrams show all the four possible routes for a suburb with N=3 streets:

Write a program that will determine the number of such distinct routes given the number of streets.

PROGRAM NAME: vans

INPUT FORMAT

  • Line 1: A single integer, N

SAMPLE INPUT (file vans.in)

4

OUTPUT FORMAT

  • Line 1: A single integer that tells how many possible distinct routes corresponding to the number of streets given in the input.

SAMPLE OUTPUT (file vans.out)

12


【译题】

描述

郊区呈矩形,有四条东西方向的街道和N(1<=N<=1000)条南北方向的街道。在郊区的西北角有一个邮局。

如N=5时,郊区如下图所示,圆点表示邮局,直线表示街道。

postal1.gif

每天邮政卡车从邮局出发,每个十字路口(包括边界和四角)经过且只经过一次。现在邮局希望知道邮政货车行驶的路线有几种。 例如,下面两幅图表示的是满足上图的两条路线

postal2.gif

另一个例子,下面四幅图表示了当N=3时的全部四种情况

postal3.gif

[编辑]格式

PROGRAM NAME: vans

INPUT FORMAT:

(file vans.in)

INPUT FORMAT 一行:一个数值N

OUTPUT FORMAT:

(file vans.out) 一行: 到INPUT中给出的街道的路径总数

[编辑]SAMPLE INPUT

 4

[编辑]SAMPLE OUTPUT

 12

wcada


【前言】参考了pty大神的详细推导,于是把题解原封不动地写在这里。

【题解】

----------------------------------------------原文始-----------------------------------------------------

预备知识:

哈密度路:由一个点出发到另外一个点结束,要求经过图中所有的点的一条路(不能重复经过点)。

哈密顿回路:从一个点出发再回到此点,经过图中所有点的一条路(不能重复经过点)。

 

问题显然的解法:对于一个n*4的图求哈密顿回路的个数。用陈丹琦的方法。

但是由于宽度只有4,所以有另外一种递推的方法,达到优化的目的:

设f[i]为前i列中,第i列的第一个格子到第二个格子的哈密度路的条数。(显然,f[n]就为答案)


1         2          3   。。i-1     i

设g[i]为前i列中,第i列的第一个格子到第四个格子的哈密顿路的条数。


1           2         3   。。i-1     i

很显然的:f[i]=f[i-1]+g[i-1]

证明第i列一二号格子的只能由两种方式得到:

1、 =f[i-1]  2、=g[i-1]

下面介绍g[i]的递推方法:

分四种情况进行讨论:g[i]=g1[i]+g2[i]+g3[i]+g4[i]

1、 =g1[i]=f[i-1]   2、 =g2[i]=f[i-1]

3、 =g3[i]=g[i-2]   4、 g4[i]

又分三种情况讨论

 =f[i-2]   =f[i-2]

有没有发现这种情况就是第i-1列的g4[i-1]

所以g4[i]=g4[i-1]+f[i-2]*2=g[i-1]-g1[i-1]-g2[i-1]-g3[i-1]+f[i-2]*2=g[i-1]-g[i-3]

所以g[i]=g1[i]+g2[i]+g3[i]+g4[i]=f[i-1]*2+g[i-1]+g[i-2]-g[i-3](比较优美吧。呵呵)

两式联立:f[i]=f[i-1]+g[i-1]

----------------------------------------------原文完-----------------------------------------------------

【代码1】非高精

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #include<cstdio>  
  2. using namespace std;  
  3. int n,i,f[1001],g[1001];  
  4. int main()  
  5. {  
  6.   scanf("%d",&n);  
  7.   g[1]=2;g[2]=2;g[3]=8;  
  8.   f[1]=0;f[2]=2;f[3]=4;  
  9.   for (i=4;i<=n;i++)  
  10.   {  
  11.     g[i]=f[i-1]*2+g[i-1]+g[i-2]-g[i-3];  
  12.     f[i]=f[i-1]+g[i-1];  
  13.   }  
  14.   printf("%d",f[n]);  
  15. }  

【代码2】高精

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. /* 
  2. PROG:vans 
  3. ID:juan1973 
  4. LANG:C++ 
  5. */  
  6. #include<cstdio>  
  7. using namespace std;  
  8. struct arr{int n,p[1001];}g[1001],f[1001];  
  9. int n,i;  
  10. arr chen(arr a)  
  11. {  
  12.   for (int i=1;i<=a.n;i++)  
  13.     a.p[i]*=2;  
  14.   for (int i=1;i<=a.n;i++)  
  15.     if (a.p[i]>9) {a.p[i+1]+=a.p[i]/10;a.p[i]%=10;}  
  16.   if (a.p[a.n+1]>0) a.n++;  
  17.   return a;  
  18. }  
  19. arr add(arr a,arr b)  
  20. {  
  21.   a.n=a.n>b.n?a.n:b.n;  
  22.   for (int i=1;i<=a.n;i++)  
  23.     a.p[i]+=b.p[i];  
  24.   for (int i=1;i<=a.n;i++)  
  25.     if (a.p[i]>9) {a.p[i+1]+=a.p[i]/10;a.p[i]%=10;}  
  26.   if (a.p[a.n+1]>0) a.n++;  
  27.   return a;  
  28. }  
  29. arr Minus(arr a,arr b)  
  30. {  
  31.   int i=1,j,k;    
  32.   while (i<=b.n)    
  33.   {    
  34.     if (a.p[i]>=b.p[i])a.p[i]=a.p[i]-b.p[i];    
  35.     else    
  36.     {    
  37.       j=i+1;    
  38.       while (a.p[j]==0) j++;    
  39.       a.p[j]--;    
  40.       for (k=i+1;k<j;k++) a.p[k]=9;    
  41.       a.p[i]=a.p[i]+10-b.p[i];    
  42.     }    
  43.     i++;    
  44.   }    
  45.   while (a.p[a.n]==0&&a.n>1)a.n--;    
  46.   return a;    
  47. }    
  48. int main()  
  49. {  
  50.   freopen("vans.in","r",stdin);  
  51.   freopen("vans.out","w",stdout);  
  52.   scanf("%d",&n);  
  53.   g[1].p[1]=2;g[2].p[1]=2;g[3].p[1]=8;  
  54.   g[1].n=g[2].n=g[3].n=1;  
  55.   f[1].p[1]=0;f[2].p[1]=2;f[3].p[1]=4;  
  56.   f[1].n=f[2].n=f[3].n=1;  
  57.   for (i=4;i<=n;i++)  
  58.   {  
  59.     g[i]=Minus(add(chen(f[i-1]),add(g[i-1],g[i-2])),g[i-3]);  
  60.     f[i]=add(f[i-1],g[i-1]);  
  61.   }  
  62.   for (i=f[n].n;i>0;i--)  
  63.     printf("%d",f[n].p[i]);  
  64.   printf("\n");  
  65. }  




/*ID:jinbo wuTASK: vansLANG:C++*/#include<bits/stdc++.h>using namespace std;struct node{   int a[1005];};node f[1010],g[1010];node mult(node t){    node ans;    int flag=0;    for(int i=1;i<=1000;i++)    {        int tmp=t.a[i]*2;        if(flag==1)        {            tmp+=1;            flag=0;        }        if(tmp>=10)        {            flag=1;            tmp-=10;        }        ans.a[i]=tmp;    }    return ans;}node add(node t1,node t2){    node ans;    int flag=0;    for(int i=1;i<=1000;i++)    {        int tmp=t1.a[i]+t2.a[i];        if(flag==1)        {            tmp+=1;            flag=0;        }        if(tmp>=10)        {            flag=1;            tmp-=10;        }        ans.a[i]=tmp;    }        return ans;}node minu(node t1,node t2){    node ans;    int flag=0;    for(int i=1;i<=1000;i++)    {        int tmp=t1.a[i]-t2.a[i];        if(flag==1)        {            tmp-=1;            flag=0;        }        if(tmp<0)        {            flag=1;            tmp+=10;        }        ans.a[i]=tmp;    }        return ans;}int main(){    freopen("vans.in","r",stdin);    freopen("vans.out","w",stdout);    int n;    cin>>n;    g[1].a[1]=2;g[2].a[1]=2;g[3].a[1]=8;    f[1].a[1]=0;f[2].a[1]=2;f[3].a[1]=4;    for (int i=4;i<=n;i++)    {     g[i]=minu(add(g[i-1],add(g[i-2],mult(f[i-1]))),g[i-3]);     f[i]=add(f[i-1],g[i-1]);    }    int flag=0;    for(int i=1000;i>=1;i--)    {        if(f[n].a[i]||flag)        {            cout<<f[n].a[i];            flag=1;        }    }    if(flag==0)        cout<<0;    cout<<endl;}



0 0
原创粉丝点击