SRM607 题解(除T3外)

来源:互联网 发布:工程控制系统仿真软件 编辑:程序博客网 时间:2024/04/28 03:26

T1:

题目大意:给一个串(字符集为:'a'..'z','?'),'?'代表'a'..'z'中等概率选择一个字母,问原串中期望回文子串个数。

主要思路:简单题,枚举每个子串,然后算出成为回文串的概率。


#include<iostream>#include<cstdio>#include<cstring>#include<vector>#include<string>using namespace std;string S;double calc(int l,int r,int n){double ans=1,ans1=0;while (l-1>=0 && r+1<n){if (S[l-1]!=S[r+1])if (S[l-1]!='?' && S[r+1]!='?') return ans1;if ((S[l-1]=='?' || S[r+1]=='?') && l-1!=r+1)ans=ans/26;ans1=ans1+ans;--l;++r;}return ans1;}class PalindromicSubstringsDiv1{public:double expectedPalindromes(vector <string> S1, vector <string> S2){S="";int n=S1.size();for (int i=0; i<n; ++i) S+=S1[i];n=S2.size();for (int i=0; i<n; ++i) S+=S2[i];double ans=0;n=S.size();for (int i=0; i<n; ++i){ans+=calc(i+1,i-1,n);ans+=calc(i+1,i,n);}return ans;}};



T2:

题目大意:给出两个数字串,每次可以将第一个的其中连续一段加一或者减一(注意,是循环的,即9+1=0),问最少对第一个串操作多少次才能变成第二个串。


主要思路:对于 第一个串s1[1..n]和 第二个串s2[1..n] ,对它们做差得到s3[1..n](只有0..9),s3[1..n]代表的既是对s3[1..n]操作把它变成全是0。对s3[1..n]做差得到s4[1..n](s4[i]=s3[i]-s3[i-1]),,显然将s3变为0就是将s4变成0,而且操作s3的区间操作就是对s4的两个不同位置的数进行操作(s4[i]+=d,s4[j]-=d),而且s4可以对任意一个数加一个任意数(但是相应的就要在其他某个数减去相应的数值),于是原问题变成 对s4的某些数增加一些值,增加的总和为D ,对s4得另一些数减去一些值,总和为-D,这样我们就可以dp了。

f[i][j]:代表前i个数字全变成0,且总共增加了j的最小代价。

最后f[n+1][0]就是答案

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<vector>using namespace std;const int MAXN=2510;string S1,S2;int num[MAXN],sum[MAXN];int a1[MAXN],a2[MAXN];int f[40000],g[40000];const int ZERO=20000;class CombinationLockDiv1{public:int minimumMoves(vector <string> P, vector <string> Q){int n=P.size();S1="";for (int i=0; i<n; ++i) S1+=P[i];n=Q.size();S2="";for (int i=0; i<n; ++i) S2+=Q[i];n=S1.size();for (int i=0; i<n; ++i) num[i]=S1[i]-S2[i];for (int i=1; i<=n; ++i) sum[i]=num[i]-num[i-1];sum[0]=num[0];if (n==0) return 0;for (int i=0; i<=n; ++i){while (sum[i]<0) sum[i]+=10;while (sum[i]>10) sum[i]-=10;a1[i]=10-sum[i];a2[i]=sum[i];}memset(f,63,sizeof(f));f[ZERO-a1[0]]=a1[0];f[ZERO+a2[0]]=a2[0];for (int i=0; i<n; ++i){memset(g,63,sizeof(g));for (int j=0; j<40000; ++j){if (j-a1[i+1]>=0) g[j-a1[i+1]]=min(g[j-a1[i+1]],f[j]+a1[i+1]);if (j+a2[i+1]<40000) g[j+a2[i+1]]=min(g[j+a2[i+1]],f[j]+a2[i+1]);}memcpy(f,g,sizeof(f));}//for (int i=0; i<=n; ++i) printf("%d %d\n",a1[i],a2[i]);return f[ZERO]/2;}};



0 0
原创粉丝点击