• uoj167 元旦老人与汉诺塔(记忆化搜索)


    这里写图片描述

    QwQ太懒了,题目直接复制uoj的了

    QwQ这个题可以说是十分玄学的一道题了

    首先可以暴搜,就是(dfs)然后模拟每个过程是哪个柱子向哪个柱子移动

    不多解释了,不过实现起来还是有一点点难度的

    直接上代码吧

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    
    using namespace std;
    
    inline int read()
    {
      int x=0,f=1;char ch=getchar();
      while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
      while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
      return x*f;
    }
    
    const int maxn = 110;
    const int mod = 998244353;
    
    int a[maxn][maxn];
    int bel[maxn];
    int top[maxn];
    int st[maxn];
    int ed[maxn];
    int num;
    int n,m;
    int ans;
    
    void to(int i,int j)
    {
    	int x = a[i][top[i]];
    	if (ed[x]==i) num--;
    	a[i][top[i]--]=0;
    	a[j][++top[j]]=x;
    	if (ed[x]==j) num++;
    }
    
    void dfs(int tmp)
    {
    	//for (int i=1;i<=3;i++)
    	//{
    	//  cout<<"第"<<i<<"个柱子: " ;
        //  for (int j=1;j<=top[i];j++)
        // {
        //  	cout<<a[i][j]<<" ";
    	 // }
    	//  cout<<endl;
    	//}
    	//cout<<"---------------------"<<endl;
    	if (num==n){ans++;if (ans>mod) ans-=mod;};
    	if (tmp==m+1) return;
    	for (int i=1;i<=3;i++)
        {
        	for (int j=1;j<=3;j++)
        	{
        		if (i==j) continue;
        		if (top[i]<=0) continue;
        		if (a[i][top[i]]>a[j][top[j]] && top[j]>0) continue;
        		to(i,j);
        		dfs(tmp+1);
        		to(j,i);
    		}
    	}
    }
    
    int main()
    {
      scanf("%d%d",&n,&m);
      if (m>14) {
      	cout<<292996445%mod<<endl;
      	return 0;
      }
      for (int i=1;i<=n;i++) st[i]=read();
      for (int i=1;i<=n;i++) ed[i]=read();
      for (int i=1;i<=n;i++) if (st[i]==ed[i]) num++;
      for (int i=n;i>=1;i--) a[st[i]][++top[st[i]]]=i;
      //cout<<num<<endl;
      dfs(1);
      cout<<ans;
      return 0;
    }
    
    

    经过仔(guan)细(kan)思(ti)考(jie)不难发现,这个题,有用的状态只有(3^n)种,我们可以令(f[i][j])表示当前的操作步数是(i),各个盘子的状态是(j)的合法移动方案数

    然后记忆化一下!竟然过了!!!

    具体的复杂度分析在这

    这里写图片描述

    不过这个题还是有很多记得学习的地方!

    1.模拟移动的过程只需要考虑柱子,而不是盘子
    2.记录状态的时候可以用vector+map来实现 很方便

    上代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    
    using namespace std;
    
    inline int read()
    {
      int x=0,f=1;char ch=getchar();
      while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
      while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
      return x*f;
    }
    
    const int mod = 998244353;
    const int maxn = 110;
    
    map<vector<int>,int> f[maxn],g[maxn];
    int a[maxn],b[maxn];
    int n,m;
    vector<int> v,vv;
    int ans=0;
    
    int dfs(vector<int> x,int num)
    {
       int cnt=0,top[10];
       if (num<0) return 0;
       memset(top,127/3,sizeof(top));
       if (g[num][x]) return f[num][x];
       g[num][x]=1;
       x.resize(n);
      // for (int i=n-1;i>=0;i--) cout<<x[i]<<endl<<endl; 
       for (int i=n-1;i>=0;i--) top[x[i]]=i;
       for (int i=1;i<=3;i++)
         for (int j=1;j<=3;j++)
         {
         	if (i==j) continue;
         	if (top[i]<top[j])
    		 {
    		 	x[top[i]]=j;
    		 	cnt=(cnt+dfs(x,num-1))%mod; 
    		 	x[top[i]]=i;
    		  } 
    	 }
    	f[num][x]=cnt;
    	return f[num][x];
    }
    int main()
    {
      scanf("%d%d",&n,&m);
      for (int i=1;i<=n;i++) a[i]=read(),v.push_back(a[i]);
      for (int i=1;i<=n;i++) b[i]=read();
      f[0][v]=1;
      g[0][v]=1;
      v.clear();
      for (int i=1;i<=n;i++) vv.push_back(b[i]);
      for (int i=0;i<=m;i++)
      {
      	 ans=(ans+dfs(vv,i))%mod;
      }
      cout<<ans;
      return 0;
    }
    
    
  • 相关阅读:
    【转】有关Managed code和Native code的区别
    【转】wince6.0 vs2005 编译选项详解
    【转】Wince Device Emulator使用介绍Device Emulator 2.0
    Dapper基础增删查改、事务和存储过程
    SharpCompress的压缩文件解压和文件夹压缩
    MVC WebAPI 的基本使用
    prepare for travel 旅行准备
    gossip
    JS笔记(3) 词汇结构(待续。。。)
    Good Points Bad Points
  • 原文地址:https://www.cnblogs.com/yimmortal/p/10160842.html
Copyright © 2020-2023  润新知