zoukankan      html  css  js  c++  java
  • $P2453 [SDOI2006] $最短距离

    #$Description$ [题面](https://www.luogu.org/problem/P2453) 题面比较复杂,大概就是有几个操作函数要求将起始字符串变换为目标字符串,每个操作有代价,求代价最小值 #$Solution$ 其实很多状态压缩类动态规划可以转换成最短路问题,只需要将状态压缩为一个点就行,一般处理变换操作可以使用这种方法。

    实际上最短路问题就是在图上跑(DP),但由于(DP)转移受顺序限制需要在拓扑序上跑,而(dijkstra)只需要指定从起点到终点就行。

    在这类题中,我们建出来的图就是一个状态转移图,而一般的状压(DP)就是在图上跑(DP),和(dijkstra)是等效的。

    对于这个题,关键点在于如何设计状态和连边建图

    (Solution)

    这道题有一个比较显然的性质:就对于最优变换方案,每个时刻目标串一定是最终串的前缀,源串一定是起始串的后缀。

    证明:假设当前目标串不是最终串的前缀,那么有两种可能:
    (1.)长度超过最终串:那就必须删除,这和在插入前删除是等效的
    (2.)目标串有字符不匹配最终串,那么之后还需要(delete)或者按之前的路修改回去,不如提前就修改或者直接(delete)

    有了这个性质,状态就比较好表示了,只有((lena+1) imes(lenb+1))种状态

    Me0ip4.png

    状态计算函数就是这个

    int id(int x,int y)//x是目标串长度,y是源串长度 
    {
    	return x*(lena+1)+y+1;
    }
    

    考虑如何连边

    操作一、二、四是比较显然的,操作三要注意判断一下,相同才能连边,操作五同理,对于操作清空要特别注意,如果你直接(id(i,j)->id(i,0))是错误的,假设(j)(0),那么根据题面就可以不断删除,而代价是(-1),所以要特别判断这个情况

    void link()
    {
    	for(re int i=0;i<=lenb;++i)
    	 for(re int j=0;j<=lena;++j)
    	 {
    	 	if(j>=1) add(id(i,j),id(i,j-1),w[1]);//del
    	 	if(j>=1&&i<lenb)
    	 	{
    	 		add(id(i,j),id(i+1,j-1),w[2]);//replace任何情况都行 
    	 		if(B[i+1]==A[lena-j+1]) add(id(i,j),id(i+1,j-1),w[3]);//相等则可以直接copy 
    		}
    		if(i<lenb)
    		{
    			add(id(i,j),id(i+1,j),w[4]);
    		}
    		if(j>=2&&i<=lenb-2)
    		{
    			if(B[i+1]==A[lena-j+2]&&B[i+2]==A[lena-j+1])
    			add(id(i,j),id(i+2,j-2),w[5]);//判断 
    		}
    		if(i==lenb&&j!=0)//这里一定要注意 
    		{
    			add(id(i,j),id(i,0),j*w[1]-1);
    		}
    	 }
    }
    

    然后加个(dijkstra)(id(0,lena))跑到(id(lenb,0))即可

    完整代码

    (Code)

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<queue>
    #include<algorithm>
    #define re register
    #define maxn 200010
    #define INF 0x3f3f3f3f
    using namespace std;
    inline int read()
    {
    	int x=0,f=1; char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    	return x*f;
    }
    struct Edge{
    	int v,w,nxt;
    }e[maxn<<2];
    int w[101],cnt,head[maxn],vis[maxn];
    char A[220],B[220];
    int lena,lenb,T,S,dis[maxn];
    int id(int x,int y)//x是目标串长度,y是源串长度 
    {
    	return x*(lena+1)+y+1;
    }
    inline void add(int u,int v,int w)
    {
    	e[++cnt].v=v;
    	e[cnt].w=w;
    	e[cnt].nxt=head[u];
    	head[u]=cnt;
    }
    struct node{
    	int u,d;
    	bool operator <(const node&rhs) const{
    		return rhs.d<d;
    	}
    };
    priority_queue<node> q;
    void dijkstra(int s)
    {
    	while(!q.empty()) q.pop();
    	q.push((node){s,0});
    	memset(dis,INF,sizeof(dis));
    	dis[s]=0;
    	while(!q.empty())
    	{
    		node now=q.top();
    		q.pop();
    		if(vis[now.u]) continue;
    		vis[now.u]=1;
    		for(int i=head[now.u];i;i=e[i].nxt)
    		{
    			int ev=e[i].v;
    			if(dis[ev]>dis[now.u]+e[i].w)
    			{
    				dis[ev]=dis[now.u]+e[i].w;
    				q.push((node){ev,dis[ev]});
    			}
    		}
    	}
    }
    void link()
    {
    	for(re int i=0;i<=lenb;++i)
    	 for(re int j=0;j<=lena;++j)
    	 {
    	 	if(j>=1) add(id(i,j),id(i,j-1),w[1]);//del
    	 	if(j>=1&&i<lenb)
    	 	{
    	 		add(id(i,j),id(i+1,j-1),w[2]);//replace任何情况都行 
    	 		if(B[i+1]==A[lena-j+1]) add(id(i,j),id(i+1,j-1),w[3]);//相等则可以直接copy 
    		}
    		if(i<lenb)
    		{
    			add(id(i,j),id(i+1,j),w[4]);
    		}
    		if(j>=2&&i<=lenb-2)
    		{
    			if(B[i+1]==A[lena-j+2]&&B[i+2]==A[lena-j+1])
    			add(id(i,j),id(i+2,j-2),w[5]);//判断 
    		}
    		if(i==lenb&&j!=0)//这里一定要注意 
    		{
    			add(id(i,j),id(i,0),j*w[1]-1);
    		}
    	 }
    }
    
    int main()
    {
        cin>>A+1,lena=strlen(A+1);
        cin>>B+1,lenb=strlen(B+1);
        for(re int i=1;i<=5;++i) w[i]=read();
        S=id(0,lena);
        T=id(lenb,0);
        link();
        dijkstra(S);
        printf("%d
    ",dis[T]);
    	return 0;
    }
    
    
  • 相关阅读:
    CF1202F You Are Given Some Letters...
    CF1178E Archaeology
    PTA (Advanced Level) 1005 Spell It Right
    PTA (Advanced Level) 1004 Counting Leaves
    Qt5——从零开始的Hello World教程(Qt Creator)
    PTA (Advanced Level) 1003 Emergency
    PTA (Advanced Level) 1002 A+B for Polynomials
    HDU 1272 小希的迷宫
    FZU 2150 Fire Game
    HihoCoder
  • 原文地址:https://www.cnblogs.com/Liuz8848/p/11824466.html
Copyright © 2011-2022 走看看