我昨天晚上才知道原来四省赛的题目可以在NEU OJ上提交,附上网址 http://acm.neu.edu.cn/hustoj/
这道题现场做的时候被我想复杂了,我已开始把这道题当做贪心+dp来做了,搞了一个三维的dp方程,复杂度是o(10^9)。当时的想法是,最优的一定是把T变成F,然后如果连续的F或T的话,那么先把他们合并成一堆,这样每次能在这堆中走的长度就已知了,然后再把T组成的一堆,如果是奇数,那么我们就留下一个,如果是偶数,那么就直接扔掉这一堆,再把相邻的两个F堆合并成一对。。。然后最终的形式就是有n个F堆,每两个堆之间用一个T隔开来,求最长路,这个样子一个三维dp就出来了,算下复杂度,然后找优化,结果就一直跪在这里了。。。
后来听了裁判的讲解,尼玛。。。这么水。其实一开始就搞错了,直接在原序列上进行操作就好了(强行要分堆,增加游戏难度)。
下面写一下dp方程:
dp[i][j][k]:i代表前i个命令,j代表改变了j次,k = 0代表向右走的最长路,k = 1代表向左做的最长路,
dp[i][j][0] = max(dp[i-1][j][0] + (执行第i个命令走出的步数(-1,0,1),具体怎么搞可以看代码),dp[i-1][j-1][0])+ (执行第i个命令走出的步数(-1,0,1),具体怎么搞可以看代码));
同理dp[i][j][1]。
注意一下边界条件,这道题马上就可以ac了。
下面附上ac代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #define ll long long #define FOR(i,x,y) for(int i = x;i < y;i ++) #define IFOR(i,x,y) for(int i = x;i > y;i --) using namespace std; const int M = 1005; const int N = 505; int dp[M][N][2],mat[M],n,m; char str[M]; int dir(int i,int j){ return (mat[i] + j) % 2; } int main() { //freopen("test.in","r",stdin); int t,tCase = 0; scanf("%d",&t); while(t--){ scanf("%s%d",str,&m); n = strlen(str); mat[0] = 0; FOR(i,1,n+1){ int tem = str[i-1] == 'T' ? 1 : 0; mat[i] = mat[i-1] + tem; } dp[0][0][0] = dp[0][0][1] = 0; FOR(i,0,m+1){ if(str[0] == 'T'){ dp[1][i][0] = i%2; dp[1][i][1] = 0 - dp[1][i][0]; } else{ dp[1][i][0] = (i+1)%2; dp[1][i][1] = 0 - dp[1][i][0]; } } FOR(i,1,n+1){ int d = mat[i-1]%2; if(str[i-1] == 'T'){ dp[i][0][0] = dp[i-1][0][0]; dp[i][0][1] = dp[i-1][0][1]; } else{ if(d){ dp[i][0][1] = dp[i-1][0][1] + 1; dp[i][0][0] = dp[i-1][0][0] - 1; } else{ dp[i][0][0] = dp[i-1][0][0] + 1; dp[i][0][1] = dp[i-1][0][1] - 1; } } } FOR(i,2,n+1){ FOR(j,1,m+1){ int d = dir(i-1,j); if(str[i-1] == 'T'){ dp[i][j][0] = dp[i-1][j][0]; dp[i][j][1] = dp[i-1][j][1]; } else{ if(d){ dp[i][j][1] = dp[i-1][j][1] + 1; dp[i][j][0] = dp[i-1][j][0] - 1; } else{ dp[i][j][0] = dp[i-1][j][0] + 1; dp[i][j][1] = dp[i-1][j][1] - 1; } } d = dir(i-1,j-1); if(str[i-1] == 'F'){ dp[i][j][0] = max(dp[i-1][j-1][0],dp[i][j][0]); dp[i][j][1] = max(dp[i-1][j-1][1],dp[i][j][1]); } else{ if(d){ dp[i][j][1] = max(dp[i][j][1],dp[i-1][j-1][1]+1); dp[i][j][0] = max(dp[i][j][0],dp[i-1][j-1][0]-1); } else{ dp[i][j][1] = max(dp[i][j][1],dp[i-1][j-1][1]-1); dp[i][j][0] = max(dp[i][j][0],dp[i-1][j-1][0]+1); } } } } printf("Case $%d: ",++tCase); printf("%d ",max(dp[n][m][0],dp[n][m][1])); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。