• 【最短路】【Heap-dijkstra】hihocoder 1587 ACM-ICPC国际大学生程序设计竞赛北京赛区(2017)网络赛 J. Typist's Problem


    题意:给你一个串,仅含有a~g,且每个字母只出现最多一次。和一个光标初始位置,以及一个目标串,问你最少要多少的代价变化成目标串。

    有五种操作:在光标前添加一个未出现过的字母,代价1。

    删除光标前或者光标后的字母,代价1。

    光标左移或者右移,代价0.5。

    哈希,把串弄成一个八进制数,加上一个光标位置,状态数不超过8^8。

    直接跑dijkstra即可。

    要注意初始化的时候,可以单独记一个数组,表示用过的状态,仅仅重置这些状态,防止初始化复杂度过高。

    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<cstring>
    using namespace std;
    char s1[10],s2[10];
    int pp,len1,len2,d[17000000],pw[10];
    bool vis[17000000],cant[8];
    int st[17000000],En;
    struct Node{
    	int u,d;
    	Node(const int &u,const int &d){
    		this->u=u;
    		this->d=d;
    	}
    	Node(){}
    };
    bool operator < (const Node &a,const Node &b){
    	return a.d>b.d;
    }
    priority_queue<Node>Heap;
    int main(){
    //	freopen("j.in","r",stdin);
    	memset(d,0x7f,sizeof(d));
    	pw[0]=1;
    	for(int i=1;i<=8;++i){
    		pw[i]=pw[i-1]*8;
    	}
    	while(scanf("%s%d%s",s1,&pp,s2)!=EOF){
    		memset(cant,0,sizeof(cant));
    		bool flag=1;
    		while(!Heap.empty()){
    			Heap.pop();
    		}
    		En=0;
    		int U=0,len1=strlen(s1),len2=strlen(s2);
    		for(int i=0;i<len2;++i){
    			if(cant[s2[i]-'a'+1]){
    				flag=0;
    				break;
    			}
    			cant[s2[i]-'a'+1]=1;
    		}
    		if(!flag){
    			puts("-1");
    			continue;
    		}
    		for(int i=0;i<len1;++i){
    			U=U*8+s1[i]-'a'+1;
    		}
    		U=U*8+pp;
    		int goal=0;
    		for(int i=0;i<len2;++i){
    			goal=goal*8+s2[i]-'a'+1;
    		}
    		Heap.push(Node(U,0));
    		d[U]=0;
    		st[++En]=U;
    		while(!Heap.empty()){
    			Node now=Heap.top(); Heap.pop();
    			if(!vis[now.u]){
    				if(now.u/8==goal){
    					break;
    				}
    				vis[now.u]=1;
    				int U=now.u;
    				int len=0;
    				int gbp=U%8; U/=8;
    				memset(cant,0,sizeof(cant));
    //				char S[10];
    				while(U){
    					cant[U%8]=1;
    //					S[len++]=U%8+'a'-1;
    					++len;
    					U/=8;
    				}
    //				for(int i=0;i<len;++i){
    //					putchar(S[i]);
    //				}
    //				puts("");
    				//plus
    				if(len<7){
    					U=now.u;
    					U-=(U%pw[len-gbp+1]);
    					U*=8;
    					U+=(now.u%pw[len-gbp+1]);
    					for(int i=1;i<=7;++i){
    						if(!cant[i]){
    							int tU=U+i*pw[len-gbp+1];
    							++tU;
    							if(d[tU]>d[now.u]+2){
    								d[tU]=d[now.u]+2;
    								Heap.push(Node(tU,d[tU]));
    								st[++En]=tU;
    							}
    						}
    					}
    				}
    				//delete
    				if(len>0){
    					if(gbp>0){
    						U=now.u%pw[len-gbp+1];
    						int tmp=now.u;
    						tmp/=pw[len-gbp+2];
    						tmp*=pw[len-gbp+1];
    						U+=tmp;
    						--U;
    						if(d[U]>d[now.u]+2){
    							d[U]=d[now.u]+2;
    							Heap.push(Node(U,d[U]));
    							st[++En]=U;
    						}
    					}
    					if(gbp<len){
    						U=now.u%pw[len-gbp];
    						int tmp=now.u;
    						tmp/=pw[len-gbp+1];
    						tmp*=pw[len-gbp];
    						U+=tmp;
    						if(d[U]>d[now.u]+2){
    							d[U]=d[now.u]+2;
    							Heap.push(Node(U,d[U]));
    							st[++En]=U;
    						}
    					}
    				}
    				//move
    				if(gbp>0){
    					if(d[now.u-1]>d[now.u]+1){
    						d[now.u-1]=d[now.u]+1;
    						Heap.push(Node(now.u-1,d[now.u-1]));
    						st[++En]=now.u-1;
    					}
    				}
    				if(gbp<len){
    					if(d[now.u+1]>d[now.u]+1){
    						d[now.u+1]=d[now.u]+1;
    						Heap.push(Node(now.u+1,d[now.u+1]));
    						st[++En]=now.u+1;
    					}
    				}
    			}
    		}
    		printf("%.1f
    ",(double)(*min_element(d+goal*8,d+goal*8+8))*0.5);
    		for(int i=1;i<=En;++i){
    			d[st[i]]=2000000000;
    			vis[st[i]]=0;
    		}
    	}
    	return 0;
    }
  • 相关阅读:
    线段树的区间更新---A Simple Problem with Integers
    划分树---Feed the dogs
    划分树基础知识
    Treap树的基础知识
    平衡二叉树---Shaolin
    KMA & ex_KMP---Revolving Digits
    DP---Mahjong tree
    《程序员代码面试指南》第一章 栈和队列 最大值减去最小值小于或等于num的数量
    《程序员代码面试指南》第一章 栈和队列 求最大子矩阵大小
    《程序员代码面试指南》第一章 栈和队列 构造数组的MaxTree
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/7583421.html
Copyright © 2020-2023  润新知