E - Swap Editorial

Time Limit: 2 sec / Memory Limit: 1024 MB
Score : 500500 points
Given is a string SS consisting of K, E, Y.
How many strings are there that can be obtained with at most KK swaps of two adjacent characters in SS?
K, E, Y.Input is given from Standard Input in the following format:
SS KK
Print the answer.
Copy
KEY 1
Copy
3
With at most one swap, there are three strings that can be obtained: KEY, EKY, KYE.
Copy
KKEE 2
Copy
4
With at most two swaps, there are four strings that can be obtained: KKEE, KEKE, EKKE, KEEK.
Copy
KKEEYY 1000000000
Copy
90
=========================================================================
此类题也只能说很难去证明为什么这样做不会缺失或者重复
EYEK
一维代表位置,二维代表e的个数,三维代表y的个数,四维代表交换次数
而按照正确方法我们得到的是如下结果
dp[1][1][0][0]=1
dp[1][1][0][1]=0
dp[1][1][0][2]=0
dp[1][1][0][3]=0
也就是交换两次结果也是0,可是如果我们把第二个e交换到第一个位置也是一种方法,而本题正确做法确实找到离当前e最近的那一个e进行转移。这就很让人不解
EYE为例
dp[2][2][0][0]为 1,显然不正确
但其转移到 dp[3][2][1][1]的时候,Y遍历E,会遇见一个比它大的E,也就把次数给加了上去。所以我们这样做是正确的。在累积多个相同字母时,如果我们没遇见其它字母,那么答案就一直是1种,(即先不计算与不同字母的交换),直到我们把不同字母提到前面,才产生了步数的变化和方案的累加。而且这么多不合理的1并不会影响答案,因为交换次数是0,我们最终获取答案的时候,仅仅取dp[n]的。
- # include
- # include
- # include
- # include
- # include
- # include
- # include
- # include
- # include
- # include
-
-
- using namespace std;
- typedef long long int ll;
-
- const int N=32;
- const int C=N*(N-1)/2;
-
- string s;
- int K;
-
- ll dp[N][N][N][C];
-
- vector<int>kp,ep,yp;
-
- int main()
- {
- cin>>s>>K;
-
- s=" "+s;
-
-
- int n=s.size()-1;
-
- K=min(K,n*(n-1)/2);
-
- for(int i=1; i<=n; i++)
- {
- if(s[i]=='K')
- {
- kp.push_back(i);
-
- }
- else if(s[i]=='E')
- {
- ep.push_back(i);
-
- }
- else if(s[i]=='Y')
- {
-
- yp.push_back(i);
-
- }
- }
-
- int ck=kp.size();
-
- int ce=ep.size();
-
- int cy=yp.size();
-
-
-
- dp[0][0][0][0]=1;
-
-
- for(int i=0; i
- {
- for(int e=0; e<=ce; e++)
- {
- for(int y=0; y<=cy; y++)
- {
- int kk=i-e-y;
-
-
- if(kk<0||kk>ck)
- continue;
-
-
-
- for(int st=0; st<=K; st++)
- {
- if(!dp[i][e][y][st])
- continue;
-
-
-
- if (kk < ck)
- {
- int moveSteps = 0; // 把i+1位置的K往左交换
- for (int l = 0; l < e; l++) if (ep[l] > kp[kk]) moveSteps++;
- for (int l = 0; l < y; l++) if (yp[l] > kp[kk]) moveSteps++;
-
- if (st + moveSteps <= K) dp[i + 1][e][y][st + moveSteps] += dp[i][e][y][st];
- }
-
- if (e < ce)
- {
- int moveSteps = 0;
- for (int l = 0; l < kk; l++) if (kp[l] > ep[e]) moveSteps++;
- for (int l = 0; l < y; l++) if (yp[l] > ep[e]) moveSteps++;
-
- if (st + moveSteps <= K) dp[i + 1][e + 1][y][st+ moveSteps] += dp[i][e][y][st];
- }
-
- if (y < cy)
- {
- int moveSteps = 0;
- for (int l = 0; l < kk; l++) if (kp[l] > yp[y]) moveSteps++;
- for (int l = 0; l < e; l++) if (ep[l] > yp[y]) moveSteps++;
-
- if (st+ moveSteps <= K) dp[i + 1][e][y + 1][st+ moveSteps] += dp[i][e][y][st];
- }
-
- }
- }
- }
- }
-
- // EKEY
-
- // cout<
-
-
- ll res = 0;
-
- for (int i = 0; i <= K; i++) res+= dp[n][ce][cy][i];
-
- cout << res << endl;
-
-
-
- return 0;
- }