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;
- }