Codeforces Round #612 (Div. 2)
阿新 • • 發佈:2020-07-10
C. Garland
題意
給你了一個序列,包含n個數,這個序列是由1~n數字構成,但是題目給你的這個序列並不完整,讓你去補完整,那些輸入的值為0的位置的就是讓你去填數字,然後問你怎麼填,這個序列的奇偶值最小。(一個序列的奇偶值大小就是這個序列的奇數和偶數的遇見次數,例如1,4,2,3,5奇偶值就是2,因為只有1,4和2,3兩處奇數和偶數相遇)。
思路
開了一個四維的dp,dp[i][j][k][2];
第一維度表示當前的位數
第二維度表示當前已經填了多少個奇數
第三維度表示當前已經填了多少個偶數
第四維度表示當前填的這個數是奇數還是偶數。
dp維度表示好了狀態轉移方程就很清楚了,當奇數和偶數相遇時就加一。
程式碼
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; const int N=105; int dp[N][N][N][2]; int pre[N]; int a[N]; int os,js; int main() { int n; scanf("%d",&n); os=n/2; js=n-os; for(int i=1; i<=n; i++) { scanf("%d",&a[i]); if(a[i]>0) { if(a[i]%2==0) { os--; } else { js--; } pre[i]=pre[i-1]; } else { pre[i]=pre[i-1]+1; } } memset(dp,0x3f3f3f,sizeof(dp)); dp[0][0][0][1]=0; dp[0][0][0][0]=0; for(int i=1; i<=n; i++) { for(int j=0; j<=js; j++) { for(int k=0; k<=os; k++) { if(a[i]<=0) { if(j+k<=pre[i]) { if(j==0&&k!=0) { dp[i][j][k][0]=min(dp[i-1][j][k-1][0],dp[i-1][j][k-1][1]+1); dp[i][j][k][1]=min(dp[i-1][j][k][0]+1,dp[i-1][j][k][1]); } else if(k==0&&j!=0) { dp[i][j][k][0]=min(dp[i-1][j][k][0],dp[i-1][j][k][1]+1); dp[i][j][k][1]=min(dp[i-1][j-1][k][0]+1,dp[i-1][j-1][k][1]); } else if(k==0&&j==0) { dp[i][j][k][0]=min(dp[i-1][j][k][0],dp[i-1][j][k][1]+1); dp[i][j][k][1]=min(dp[i-1][j][k][0]+1,dp[i-1][j][k][1]); } else { dp[i][j][k][0]=min(dp[i-1][j][k-1][0],dp[i-1][j][k-1][1]+1); dp[i][j][k][1]=min(dp[i-1][j-1][k][0]+1,dp[i-1][j-1][k][1]); } } } else { if(j+k<=pre[i]) { if(a[i]%2==0) { dp[i][j][k][0]=min(dp[i-1][j][k][0],dp[i-1][j][k][1]+1); } else { dp[i][j][k][1]=min(dp[i-1][j][k][0]+1,dp[i-1][j][k][1]); } } } } } } printf("%d\n",min(dp[n][js][os][0],dp[n][js][os][1])); return 0; }
B. Young Explorers
題意
從一些資料中選三組滿足一定關係的字串,暴力是三層迴圈,一般要轉化為兩層,然後得到第三個。