2014.12.14 搜索练习

挑战编程程序设计 搜索练习

8.6.1棋盘上的象

题目大意:在n*n的棋盘上放象,每个象的对角线上不能有别的象,求总共的方案数。

思路:搜索,肯定超时。dp~~排列组合~~又不会,只能打表了,好凶残。直接a(放0头象竟然是1种方案)。

 

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int d1[20]={0},d2[20]={0},n,k;
long long ans;
void work(int i,int j,int di)
{
    int dd1,dd2,yu;
    if (di>k) 
    {
        ++ans;
        return;
    }
    if (i>n||j>n) return;
    yu=(n-i)*n+n-j+1;
    if (yu<k-di+1) return;
    dd1=i-j+8;dd2=i+j;
    if (d1[dd1]==0&&d2[dd2]==0)
    {
        ++d1[dd1];++d2[dd2];
        if (j==n) work(i+1,1,di+1);
        else work(i,j+1,di+1);
        --d1[dd1];--d2[dd2];
    }
    if (j==n) work(i+1,1,di);
    else work(i,j+1,di);
}
int main()
{
    while(scanf("%d%d",&n,&k)==2)
    {
        if (n==0&&k==0) break;
        ans=0;
        memset(d1,0,sizeof(d1));
        memset(d2,0,sizeof(d2));
        work(1,1,1);
        printf("%lld\n",ans);
    }
}
正常搜索
#include<iostream>
#include<cstdio>
using namespace std;
long long biao[9][65]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,9,26,26,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,16,92,232,260,112,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,25,240,1124,2728,3368,1960,440,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,36,520,3896,16428,39680,53744,38368,12944,1600,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,49,994,10894,70792,282248,692320,1022320,867328,389312,81184,5792,128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,64,1736,26192,242856,1444928,5599888,14082528,22522960,22057472,12448832,3672448,489536,20224,256,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int main()
{
    int n,k;
    while(scanf("%d%d",&n,&k)==2)
    {
        if (n==0&&k==0) break;
        printf("%lld\n",biao[n][k]);
    }
}
打表

 

8.6.2十五数码

题目大意:常见的十五数码问题,输出步骤(不一定是最优解)

思路:借这个题学习了一下a*算法,最关键的估价函数(这个题中,也能重视到估价函数的重要性,这个题目f(n)=g(n)+4/3h(n),话说为什么要4/3?只是实践?不加4/3就a不了),顺带练习了map和优先队列。其实a*算法,比较好理解,一个open优先队列,一个close map关系,对于每个优先队列中得分最低的元素进行处理,加入close、四个方向,然后将拓展到的判断是否已经出现在close中,若出现,就从close中把原来的删掉(原来的步数多的情况下),然后加入到open中。重复上述操作直到找到答案或者open为空。最后就是输出步骤了,当然,这道题中还要先判断是否有解,再做,否则会超时的。。。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<cmath>
#include<map>
using namespace std;
struct use{
    int num[16],kg,stt,st[100],score;
    long long cant;
}a;
bool operator<(use x,use y)
    {
    return x.score>y.score;
    }
long long jie[16]={0};
int move[4]={0},wy[4]={-1,1,-4,4},manha[16][16]={0};
bool noans(struct use xx)
{
    int ge=0,i,j;
    for (i=0;i<15;++i)
      for (j=i+1;j<=15;++j)
        if (xx.num[i]<xx.num[j]&&(xx.num[i]!=0)) ++ge;
    ge+=(xx.kg/4)+1;
    if (ge%2==0) return true;
    else return false;
}
void manh()
{
    int i,j,x1,x2,y1,y2;
    for (i=0;i<16;++i)
      for (j=0;j<16;++j)
      {
          x1=i%4;y1=i/4;
          x2=j%4;y2=j/4;
          manha[i][j]=(abs(x1-x2)+abs(y1-y2));
      }
}
long long cantor(struct use xx)
{
    int i,j,ge=0;
    long long ans;
    for (i=0;i<=14;++i)
    {
        ge=0;
        for (j=i+1;j<=15;++j)
          if (xx.num[i]>xx.num[j]) ++ge;
        ans+=jie[15-i]*ge;
    }
    return ans;
}
int sco(struct use xx,int dep)
{
    int i,j,ans,x1,y1,x2,y2;
    ans=0;
    for (i=0;i<=15;++i)
        ans+=manha[i][(xx.num[i]+15)%16];
    return dep+(4*ans/3);
}
bool comp(struct use xx)
{
    int i;
    if (xx.num[15]!=0) return false;
    for (i=0;i<15;++i)
      if (xx.num[i]!=i+1) return false;
    return true;
}
void explore(struct use xx)
{
    int i,j,x,la;
    move[0]=move[1]=move[2]=move[3]=-1;
    x=xx.kg;la=-1;
    if (xx.stt>0) la=xx.st[xx.stt];
    if (x%4>0&&la!=1) move[0]=0;
    if (x%4<3&&la!=0) move[1]=1;
    if (x/4>0&&la!=3) move[2]=2;
    if (x/4<3&&la!=2) move[3]=3;
}
void print(struct use xx)
{
    int i;
    for (i=1;i<=xx.stt;++i)
    {
        if (xx.st[i]==0) printf("L");
        if (xx.st[i]==1) printf("R");
        if (xx.st[i]==2) printf("U");
        if (xx.st[i]==3) printf("D");
    }
    printf("\n");
}
void work()
{
    int i,j;
    struct use ne,th;
    a.score=sco(a,0);
    a.stt=0;
    a.cant=cantor(a);
    priority_queue < use > open;
    map < long long,int> close;
    open.push(a);
    while(!open.empty())
    {
      th=open.top();
      open.pop();
      close.insert(make_pair< long long,int>
                   (th.cant,th.score));
      if (comp(th))
      {
          print(th);
          return;
      }
      explore(th);
      for (i=0;i<4;++i)
       {
          if (move[i]==-1) continue;
          ne=th;
          ne.kg=th.kg+wy[i];
          ne.num[th.kg]=ne.num[ne.kg];ne.num[ne.kg]=0;
          ne.stt=th.stt+1;ne.st[ne.stt]=i;
          if (ne.stt>50) continue;
          ne.cant=cantor(ne);
          ne.score=sco(ne,ne.stt);
          map < long long,int >::iterator it =close.find(ne.cant);
          if (it!=close.end())
          {
               if (ne.score>=(*it).second)
                 continue;
               close.erase(it);
          }
          open.push(ne);
      }
    }
}
int main()
{
    int n,i,j,cci;
    manh();
    jie[1]=1;
    for (i=2;i<=15;++i)
      jie[i]=jie[i-1]*i;
    scanf("%d",&n);
    for (cci=1;cci<=n;++cci)
    {
        for (i=0;i<16;++i)
        {
          scanf("%d",&a.num[i]);
          if (a.num[i]==0) a.kg=i;
        }
        if (comp(a)) printf("\n");
        else
        {
          if (noans(a)) printf("This puzzle is not solvable.\n");
          else work();
        }
    }
}
View Code

 

 

8.6.3队伍

题目大意:n个人站队,恰有p个人比左边的人都高,恰有r个人比右边的人都高,求总的方案数。

思路:搜索,一开始是按位置搜的,超时妥妥的。之后改了搜索方法,从高的往小的放,如果当前的人放在已放过的左边;就相当于多了一个比左边人都高的,如果当前的人放在已放过的右边,就相当于多了一个比右边人都高的;如果放在之间的话,就没有变化。然后搜出来的相对要快,可是还是没法满足我们的要求,于是又用了打表,打了十分钟的表,终于a了。

 

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n;
long long ans=0;
bool use[14]={false};
void work(int i,int ll,int rr,int le,int re)
{
    int j;
    if (i>n&&le==0&&re==0)
    {
        ++ans;
        return;
    }
    if (ll-1<le) return;
    if (n-rr<re) return; 
    if (i==1)
    {
        for (j=le;j<=n-re+1;++j)
        {
            use[j]=true;
            work(i+1,j,j,le-1,re-1);
            use[j]=false;
        }
    }
    else
    {
      for (j=le;j<=n-re+1;++j)
      {
          if (j<1||j>n) continue;
        if (!use[j])
        {
            use[j]=true;
          if (j<ll&&le>0) work(i+1,j,rr,le-1,re);
          if (j>ll&&j<rr) work(i+1,ll,rr,le,re);
          if (j>rr&&re>0) work(i+1,ll,j,le,re-1);
          use[j]=false; 
        }
      }
    }
}
int main()
{
    int i,j,ci,t,l,r;
    scanf("%d",&t);
    for (ci=1;ci<=t;++ci)
    {
        scanf("%d%d%d",&n,&l,&r);
        memset(use,false,sizeof(use));
        ans=0;
        work(1,n+1,0,l,r);
        printf("%lld\n",ans);
    }
}
正常搜索
#include<iostream>
#include<cstdio>
using namespace std;
long long ans[14][14][14]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,1,0,0,0,0,0,0,0,0,0,0,2,6,3,0,0,0,0,0,0,0,0,0,0,0,3,3,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,11,6,1,0,0,0,0,0,0,0,0,0,6,22,18,4,0,0,0,0,0,0,0,0,0,0,11,18,6,0,0,0,0,0,0,0,0,0,0,0,6,4,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,50,35,10,1,0,0,0,0,0,0,0,0,24,100,105,40,5,0,0,0,0,0,0,0,0,0,50,105,60,10,0,0,0,0,0,0,0,0,0,0,35,40,10,0,0,0,0,0,0,0,0,0,0,0,10,5,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,120,274,225,85,15,1,0,0,0,0,0,0,0,120,548,675,340,75,6,0,0,0,0,0,0,0,0,274,675,510,150,15,0,0,0,0,0,0,0,0,0,225,340,150,20,0,0,0,0,0,0,0,0,0,0,85,75,15,0,0,0,0,0,0,0,0,0,0,0,15,6,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,720,1764,1624,735,175,21,1,0,0,0,0,0,0,720,3528,4872,2940,875,126,7,0,0,0,0,0,0,0,1764,4872,4410,1750,315,21,0,0,0,0,0,0,0,0,1624,2940,1750,420,35,0,0,0,0,0,0,0,0,0,735,875,315,35,0,0,0,0,0,0,0,0,0,0,175,126,21,0,0,0,0,0,0,0,0,0,0,0,21,7,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5040,13068,13132,6769,1960,322,28,1,0,0,0,0,0,5040,26136,39396,27076,9800,1932,196,8,0,0,0,0,0,0,13068,39396,40614,19600,4830,588,28,0,0,0,0,0,0,0,13132,27076,19600,6440,980,56,0,0,0,0,0,0,0,0,6769,9800,4830,980,70,0,0,0,0,0,0,0,0,0,1960,1932,588,56,0,0,0,0,0,0,0,0,0,0,322,196,28,0,0,0,0,0,0,0,0,0,0,0,28,8,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,40320,109584,118124,67284,22449,4536,546,36,1,0,0,0,0,40320,219168,354372,269136,112245,27216,3822,288,9,0,0,0,0,0,109584,354372,403704,224490,68040,11466,1008,36,0,0,0,0,0,0,118124,269136,224490,90720,19110,2016,84,0,0,0,0,0,0,0,67284,112245,68040,19110,2520,126,0,0,0,0,0,0,0,0,22449,27216,11466,2016,126,0,0,0,0,0,0,0,0,0,4536,3822,1008,84,0,0,0,0,0,0,0,0,0,0,546,288,36,0,0,0,0,0,0,0,0,0,0,0,36,9,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,362880,1026576,1172700,723680,269325,63273,9450,870,45,1,0,0,0,362880,2053152,3518100,2894720,1346625,379638,66150,6960,405,10,0,0,0,0,1026576,3518100,4342080,2693250,949095,198450,24360,1620,45,0,0,0,0,0,1172700,2894720,2693250,1265460,330750,48720,3780,120,0,0,0,0,0,0,723680,1346625,949095,330750,60900,5670,210,0,0,0,0,0,0,0,269325,379638,198450,48720,5670,252,0,0,0,0,0,0,0,0,63273,66150,24360,3780,210,0,0,0,0,0,0,0,0,0,9450,6960,1620,120,0,0,0,0,0,0,0,0,0,0,870,405,45,0,0,0,0,0,0,0,0,0,0,0,45,10,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3628800,10628640,12753576,8409500,3416930,902055,157773,18150,1320,55,1,0,0,3628800,21257280,38260728,33638000,17084650,5412330,1104411,145200,11880,550,11,0,0,0,10628640,38260728,50457000,34169300,13530825,3313233,508200,47520,2475,55,0,0,0,0,12753576,33638000,34169300,18041100,5522055,1016400,110880,6600,165,0,0,0,0,0,8409500,17084650,13530825,5522055,1270500,166320,11550,330,0,0,0,0,0,0,3416930,5412330,3313233,1016400,166320,13860,462,0,0,0,0,0,0,0,902055,1104411,508200,110880,11550,462,0,0,0,0,0,0,0,0,157773,145200,47520,6600,330,0,0,0,0,0,0,0,0,0,18150,11880,2475,165,0,0,0,0,0,0,0,0,0,0,1320,550,55,0,0,0,0,0,0,0,0,0,0,0,55,11,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,39916800,120543840,150917976,105258076,45995730,13339535,2637558,357423,32670,1925,66,1,0,39916800,241087680,452753928,421032304,229978650,80037210,18462906,2859384,294030,19250,726,12,0,0,120543840,452753928,631548456,459957300,200093025,55388718,10007844,1176120,86625,3630,66,0,0,0,150917976,421032304,459957300,266790700,92314530,20015688,2744280,231000,10890,220,0,0,0,0,105258076,229978650,200093025,92314530,25019610,4116420,404250,21780,495,0,0,0,0,0,45995730,80037210,55388718,20015688,4116420,485100,30492,792,0,0,0,0,0,0,13339535,18462906,10007844,2744280,404250,30492,924,0,0,0,0,0,0,0,2637558,2859384,1176120,231000,21780,792,0,0,0,0,0,0,0,0,357423,294030,86625,10890,495,0,0,0,0,0,0,0,0,0,32670,19250,3630,220,0,0,0,0,0,0,0,0,0,0,1925,726,66,0,0,0,0,0,0,0,0,0,0,0,66,12,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0};
int main()
{
    int ci,n,l,r;
    scanf("%d",&ci);
    while(ci)
    {
        scanf("%d%d%d",&n,&l,&r);
        printf("%lld\n",ans[n][l][r]);
        --ci;
    }
}
打表

 

8.6.5拔河

题目大意:有n个人拔河,将这n个人尽量平分,使两队的人不相差多于1个,然后使两队的体重数相差尽量小,输出分配方案。

思路:之前做过这个题,用的是背包。用容积为总容积一半的背包,装一半的物品,然后用布尔数组保存这些,最后从一半容积处穷举,找到最优解就可以了。

 

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
bool f[101][45001]={false};
int a[101]={0};
int main()
{
    int i,j,sum=0,n,k,q,cha,summ,ci;
    scanf("%d",&ci);
    while(ci)
    {
    cin>>n;
    sum=0;
    memset(f,false,sizeof(f));
    if (n%2==0) k=n/2;
    else k=n/2+1;
    for (i=1;i<=n;++i)
    {
      cin>>a[i];
      sum+=a[i];
    }
    if (sum%2==0) summ=sum/2;
    else summ=sum/2+1;  
    for (i=0;i<=n;++i)
      f[i][0]=true;
    for (i=1;i<=n;++i)
      for (j=summ;j>=a[i];--j)
        for (q=k;q>=1;--q)
        f[q][j]=f[q][j]||f[q-1][j-a[i]];
    for (j=summ;j>=0;--j)
      if (f[k][j])
      {
          cout<<min(j,sum-j)<<" "<<max(j,sum-j)<<endl;
        break;
      }
    if (ci>1) cout<<endl;
    --ci;
    }
}
View Code

 

8.6.6伊甸园

题目大意:给定变化规则,然后判断给定状态有无前驱。

思路:理解题意用了好久。。。终于明白一个状态里面的每个元素都要同时发生变化。然后就是比较简单的搜索了(我的初始化太肮脏,本来循环就可以了,怪我不会位运算。。。)被这么一道题坑了好久,原来是while(scanf(“%d%d”,&n,&m)==2)忘了==2,一直T。。。

#include<iostream>
#include<cstdio>
using namespace std;
int rule[8][4]={0},mo[34]={0},cc[34]={0},n,m;
bool f=false;
int tepan()
{
    int i;
    if (m==0)
    {
        for (i=1;i<=n;++i)
          if (mo[i]!=0) return 0;
        return 1;
    }
    if (m==255)
    {
        for (i=1;i<=n;++i)
          if (mo[i]!=1) return 0;
        return 1;
    }
    return 2;
}
void rul()
{
    if (m>=128)
    {
        rule[7][0]=rule[7][1]=rule[7][2]=rule[7][3]=1;
        m-=128;
    }
    else
    {
        rule[7][1]=rule[7][2]=rule[7][3]=1;rule[7][0]=0;
    }
    if (m>=64)
    {
        rule[6][0]=rule[6][1]=rule[6][2]=1;rule[6][3]=0;
        m-=64;
    }
    else
    {
        rule[6][1]=rule[6][2]=1;rule[6][0]=rule[6][3]=0;
    }
    if (m>=32)
    {
        rule[5][1]=rule[5][3]=rule[5][0]=1;rule[5][2]=0;
        m-=32;
    }
    else
    {
        rule[5][1]=rule[5][3]=1;rule[5][0]=rule[5][2]=0;
    }
    if (m>=16)
    {
        rule[4][1]=rule[4][0]=1;rule[4][2]=rule[4][3]=0;
        m-=16;
    }
    else
    {
        rule[4][1]=1;rule[4][0]=rule[4][2]=rule[4][3]=0;
    }
    if (m>=8)
    {
        rule[3][1]=0;rule[3][2]=rule[3][3]=rule[3][0]=1;
        m-=8;
    }
    else
    {
        rule[3][1]=rule[3][0]=0;rule[3][2]=rule[3][3]=1;
    }
    if (m>=4)
    {
        rule[2][1]=rule[2][3]=0;rule[2][2]=rule[2][0]=1;
        m-=4;
    }
    else
    {
        rule[2][1]=rule[2][3]=rule[2][0]=0;rule[2][2]=1;
    }
    if (m>=2)
    {
        rule[1][1]=rule[1][2]=0;rule[1][0]=rule[1][3]=1;
        m-=2;
    }
    else
    {
        rule[1][0]=rule[1][1]=rule[1][2]=0;rule[1][3]=1;
    }
    if (m>=1)
    {
        rule[0][0]=1;rule[0][1]=rule[0][2]=rule[0][3]=0;
        m-=1;
    }
    else 
    {
        rule[0][0]=rule[0][1]=rule[0][2]=rule[0][3]=0;
    }
}
void work(int i)
{
    int j,k;
    if (i>n)
    {
        if (cc[0]!=cc[n]) return;
        if (cc[1]!=cc[i]) return;
        f=true; return;
    }
    for (j=0;j<=7;++j)
    {
        if (rule[j][1]!=cc[i-1]) continue;
        if (rule[j][2]!=cc[i]) continue;
        if (rule[j][0]!=mo[i]) continue;
        cc[i+1]=rule[j][3];
        work(i+1);
        if (f) return;
    }
}
int main()
{
    int i,ff;
    char ch;
    while(scanf("%d%d",&m,&n)==2)
    {
        scanf("%*c");
        for (i=1;i<=n;++i)
        {
          scanf("%c",&ch);
          mo[i]=ch-'0';
        }
        ff=tepan();
        if (ff==0) 
           printf("GARDEN OF EDEN\n");
        else
        {
          if (m==204||ff==1)
            printf("REACHABLE\n");
          else
          {
               rul();
               f=false;
               cc[0]=0;cc[1]=0;
               work(1);
               if (!f)
               {
                 cc[0]=0;cc[1]=1;
                 work(1);
                 if (!f)
                 {
                       cc[0]=1;cc[1]=0;
                       work(1);
                       if (!f)
                       {
                           cc[0]=1;cc[1]=1;
                           work(1);
                       }
                 }
             }
             if (f) printf("REACHABLE\n");
             else printf("GARDEN OF EDEN\n");
          }
        }
    }
}
View Code

 

posted @ 2014-12-14 19:33  Rivendell  阅读(231)  评论(0编辑  收藏  举报