codeforces1202B You Are Given a Decimal String... 记忆化搜索或Floyd最短路算法
Posted aya-uchida
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了codeforces1202B You Are Given a Decimal String... 记忆化搜索或Floyd最短路算法相关的知识,希望对你有一定的参考价值。
网址:http://codeforces.com/problemset/problem/1202/B
题意:
这个题真的挺绕的,草(中日双语),就是给出一串序列,然后你可以往里面填数,使得填数后的序列可以被$x-y$计数器输出。$x-y$计数器的工作方式是:初始是$0$,每一步加上$x$或者加上$y$,然后输出对$10$取余的数。输出$0<x,y<10$的$x-y$计数器下需要添加的字符数最小值,若无法满足输出$-1$。
题解:
草,比赛时靠着网上的资料一步步写出的记忆化搜索的方法,想不出正解是转化成最短路。
一、dfs记忆化搜索
对于不断对$10$取余的序列,不超过$10$轮就会出现相同的数字,因此,$dfs$最多只有$10$轮,遇到重复的数字时,如果搜索的层数小于原来保存的层数,则更新,大于等于则返回保证了搜索结果的层数都是最小值。然后字符串的一个字符到下一个字符相当于状态转移,直接读取保存下来的状态即可。
AC代码:$(600ms)$
#include <bits/stdc++.h> using namespace std; int dp[15][15][15],res[15][15]; char str[2000005]; int x,y; void dfs(int div,bool mode,int cur) if(!mode) cur=(cur+x)%10; if(dp[x][y][cur]!=-1) if(div>=dp[x][y][cur]) return; dp[x][y][cur]=div; dfs(div+1,0,cur); dfs(div+1,1,cur); else cur=(cur+y)%10; if(dp[x][y][cur]!=-1) if(div>=dp[x][y][cur]) return; dp[x][y][cur]=div; dfs(div+1,0,cur); dfs(div+1,1,cur); void init() memset(dp,-1,sizeof(dp)); for(int i=0;i<10;++i) for(int j=0;j<10;++j) x=i,y=j; dfs(0,0,0); dfs(0,1,0); int cal(int x,int y,int len) if(len==1) return 0; int ans=0; for(int i=1;i<len;++i) int tmp; int dis=str[i]-str[i-1]; while(dis<0) dis+=10; tmp=dp[x][y][dis]; if(tmp==-1) return -1; else ans+=tmp; return ans; int main() init(); scanf("%s",str); int len=strlen(str); for(int i=0;i<10;++i) for(int j=0;j<10;++j) res[i][j]=cal(i,j,len); for(int i=0;i<10;++i) for(int j=0;j<10;++j) printf("%d%c",res[i][j],(j==9?‘\n‘:‘ ‘)); return 0;
二、floyd算法
状态转移$x->y$相当于是建立一条$x$到$y$的边权为$1$的有向边,最小值相当于是$str[i-1]->str[i],(0<i<len(str))$的最短路,所以直接建图,邻接矩阵存,对每个情况跑一遍$floyd$算法即可。
AC代码:$(200ms)$
#include <bits/stdc++.h> using namespace std; int dp[15][15],len; char str[2000005]; const int inf=0x3f3f3f3f; int solve(int x,int y) memset(dp,inf,sizeof(dp)); for(int i=0;i<10;++i) dp[i][(i+x)%10]=dp[i][(i+y)%10]=1; for(int k=0;k<10;++k) for(int i=0;i<10;++i) for(int j=0;j<10;++j) dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]); int ans=0; for(int i=1;i<len;++i) if(dp[str[i-1]-‘0‘][str[i]-‘0‘]>=inf) return -1; ans+=dp[str[i-1]-‘0‘][str[i]-‘0‘]-1; return ans; int main() scanf("%s",str); len=strlen(str); for(int i=0;i<10;++i) for(int j=0;j<10;++j) printf("%d%c",solve(i,j),(j==9?‘\n‘:‘ ‘)); return 0;
以上是关于codeforces1202B You Are Given a Decimal String... 记忆化搜索或Floyd最短路算法的主要内容,如果未能解决你的问题,请参考以下文章
[CF1202B] You Are Given a Decimal String(最短路)
Codeforces Round #645 (Div. 2) E - Are You Fired? 尺取?
Codeforces Round #645 (Div. 2) E - Are You Fired? 尺取?
Codeforces 1039D You Are Given a Tree (看题解)
(模拟)关于进制的瞎搞---You Are Given a Decimal String...(Educational Codeforces Round 70 (Rated for Div. 2))