【GDOI2017 day2】小学生语文题
来源:互联网 发布:合肥大数据产业峰会 编辑:程序博客网 时间:2024/04/30 14:23
Description
Solution
比赛的时候打了个信仰贪心,结果只拿到了10分,但是后来打完正解之后才发现贪心分答案处理好像有些问题,要是把这个纠正过来不知道还能多拿多少分。
这个很明显可以倒着DP。
设f[i][j]表示a串i~n都匹配完成,b串用到了j~n(有些可能不动,有些可能抽了出来)
我们考虑怎么转移:
我们知道i,j的状态只可能从(i+1,j),(i+1,j+1),(i,j+1)转移过来
1、从(i+1,j)转移过来,那么就是说抽出来的可以把i填满,那么判断一下现在b串这个字符的数量是否比a串这个字符的数量大(在a的i+1~n和b的j~n,预处理一个数组减一下–b[s[i]][j]-a[s[i]][i+1]),然后f[i][j]就与f[i+1][j]取一个min。
2、从(i+1,j+1)转移过来,那么就是说当前的这个位置可以不用动s[i]=st[j],那么f[i][j]与f[i+1][j+1]取一个min
上面的是不用抽出来的情况(不用贡献+1),所以要先更新状态,否则会有问题
3、从(i,j+1)转移过来,就是说现在只把j抽出来不匹配,那么f[i][j]和f[i][j+1]+1去一个min
还要预处理一下,f[n+1]的预处理,f[n+1][n+1]=0,f[n+1][n]=1,……,f[n+1][1]=n,就是一个个抽出来不匹配。
然后f[1][1]就是答案。
然后就是方案数要怎么求。我们用一个g[i][j][0,1]在更新f[i][j]的时候存储它的上一个状态的i,j
我们知道只有从(i,j+1)过来的时候才会抽出来,那么就是说在转态从(1,1)向后转移的时候,当i不变j边的时候,这些状态是要抽出来的,我是一直找出下一个不等于i的转态,然后标记(这些是不用抽出来的),然后把标记翻转一下就好了。
最后知道了这些要抽出来,那么倒着模拟一遍,先把要抽出来的放进一个桶里面,然后如果能匹配就匹配,否则把桶里的东西抽出来匹配。
最后得到了一个答案数组,要考虑相对位置,只用考虑每个i这个答案对i+1~n的答案的影响,如果影响了就+1……很简单
找方案打的有些复杂,应该还有更快的方法。不过这个好想好理解。
Code
#include<iostream>#include<stdio.h>#include<string.h>#include<algorithm>#include<math.h>#define fo(i,a,b) for(i=a;i<=b;i++)#define fod(i,a,b) for(i=a;i>=b;i--)using namespace std;const int maxn=2007;int i,j,k,l,t,n,m,ans,pan,o,x,y,hou;int f[maxn][maxn],g[maxn][maxn][2],cas,se[27][maxn];char s[maxn],st[maxn];int a[maxn][26],b[maxn][26],an[maxn][2],c[maxn];int main(){ freopen("chinese.in","r",stdin); freopen("chinese.out","w",stdout); for(scanf("%d",&cas);cas;cas--){ scanf("%s",s+1);scanf("%s",st+1);n=strlen(s+1); memset(f,127,sizeof(f));memset(g,0,sizeof(g)); pan=f[0][0];fod(i,n+1,1)f[n+1][i]=n+1-i; memset(a,0,sizeof(a));memset(b,0,sizeof(b)); fod(i,n,1){ fo(j,0,25)a[i][j]=a[i+1][j],b[i][j]=b[i+1][j]; a[i][s[i]-'a']++,b[i][st[i]-'a']++; } fod(i,n,1){ fod(j,n,1){ if(f[i+1][j]!=pan&&f[i][j]>f[i+1][j]&&b[j][s[i]-'a']-a[i+1][s[i]-'a']>0){ f[i][j]=f[i+1][j]; g[i][j][0]=i+1,g[i][j][1]=j; } if(f[i+1][j+1]!=pan&&f[i][j]>f[i+1][j+1]&&s[i]==st[j]){ f[i][j]=f[i+1][j+1]; g[i][j][0]=i+1,g[i][j][1]=j+1; } } fod(j,n,1){ if(f[i][j+1]!=pan&&f[i][j]>f[i][j+1]+1){ f[i][j]=f[i][j+1]+1; g[i][j][0]=i,g[i][j][1]=j+1; } } } printf("%d\n",f[1][1]); x=1,y=1;o=0;memset(se,0,sizeof(se));memset(c,0,sizeof(c));hou=n; while(x!=n+1){ while(g[x][y][0]==x)y=g[x][y][1]; if(g[x][y][1]!=y)c[y]++,y++; x++; } fo(i,1,n){c[i]=1-c[i];if(c[i])se[st[i]-'a'][++se[st[i]-'a'][0]]=i;} fod(i,n,1){ if(!hou)break; if(!c[i]){ while(s[hou]!=st[i]){ an[++o][0]=se[s[hou]-'a'][se[s[hou]-'a'][0]--],an[o][1]=i+1; hou--; } hou--; } } fod(j,hou,1){ i=s[j]-'a'; an[++o][0]=se[i][se[i][0]--],an[o][1]=1; } fo(i,1,o){ fo(j,i+1,o){ if(an[i][0]>=an[j][0]&&an[j][0]>=an[i][1])an[j][0]++; if(an[i][0]>an[j][1]&&an[j][1]>an[i][1])an[j][1]++; } } fo(i,1,o)printf("%d %d\n",an[i][0],an[i][1]); }}
- 【GDOI2017 day2】小学生语文题
- 【JZOJ5102】【GDOI2017 day2】小学生语文题
- GDOI2017 day2 Problem3 小学生语文题
- 【jzoj5102】【GDOI2017 day2】【小学生语文题】【动态规划】
- 【GDOI 2017 day2】小学生语文题
- 【GDOI 2017】【JZOJ 1502】小学生语文题
- 【GDOI2017第四轮模拟day2】绝版题
- 【GDOI2017 day2】凡喵识图
- 【JZOJ5100】【GDOI2017 day2】RPG
- 【JZOJ5101】【GDOI2017 day2】凡喵识图
- {题解}[jzoj5101]【GDOI2017 day2】凡喵识图
- GDKOI2016 Day2 T4 小学生数学题
- jzoj【GDOI2017第二轮模拟day2】开房间
- 【GDOI2017第二轮模拟day2】中位数
- 【GDOI2017第二轮模拟day2】开房间
- 【GDOI2017第二轮模拟day2】中位数
- 【GDOI2017第二轮模拟day2】开房间
- 【JZOJ5065】【GDOI2017第二轮模拟day2】开房间
- 【linux】记录一个配色方案putty
- 线性回归、梯度下降(Linear Regression、Gradient Descent)
- AWR视图
- 初识导函数——研究圆面积与周长的关系
- 练习题 No.9 01背包问题
- 【GDOI2017 day2】小学生语文题
- 优秀算法摘录
- javascript中设计模式之桥接模式详解(Bridge design)
- 【bzoj4553】[Tjoi2016&Heoi2016]序列
- SCALA下划线_用法
- 袁萌浅谈C919大飞机(一)
- sc32440 内核自带LED驱动
- git 出现错误 Could not resolve host: github.com
- 电脑小技巧