CF761C Dasha and Password(線性dp)

洛谷鏈接
https://www.luogu.com.cn/problem/CF761C

題目大意

給n個字符串,每個長m,初始光標都在每個字符串的開頭位置,通過移動光標,從n個字符串中各選擇一個字符,構成密碼,(移動光標時把長度爲m的字符串當做一個環),密碼必須滿足有至少一個小寫字母,至少一個數字,至少一個其他字符(# & *),求最小移動次數。

數據範圍

3<=n<=50,1<=m<=50

Solution
O(n^3)
令dp[i][j] 爲第i行選擇j類字符的最小移動次數
(j == 1 數字)
(j == 2 小寫字母)
(j == 3 其他符號)
把每一行單獨處理,最後枚舉統計最小的答案。
答案爲min(dp[i][1] + dp[j][2] + dp[k][3])
!!!注意極大值,防止dp[i][j]賦爲極大值時,三個加起來爆int。

代碼

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 1e9 + 7;
const int SZ = 100 + 5;
int n,m;//1 (0 - 9) 2 (a - z) 3 (# & *) 
char s[SZ][SZ];//dp[i][j] 第i行換成j類型的最小移動次數 
ll dp[SZ][4],ans;
int main()
{
	scanf("%d%d",&n,&m);
	for(int i = 1;i <= n;i ++ )
		for(int j = 1;j <= 3;j ++ )
		dp[i][j] = INF; 
	for(int i = 1;i <= n;i ++ ) scanf("%s",s[i] + 1);
	for(int i = 1;i <= n;i ++)
	{
		for(int j = 1;j <= 3;j ++ )
		{
			for(int k = 1;k <= m;k ++ )
			{
				if(s[i][k] >= '0' && s[i][k] <= '9') dp[i][1] = min(dp[i][1],min((ll)(k - 1),(ll)(m - k + 1))); 
				if(s[i][k] >= 'a' && s[i][k] <= 'z') dp[i][2] = min(dp[i][2],min((ll)(k - 1),(ll)(m - k + 1))); 
				if(s[i][k] == '#' || s[i][k] == '*' || s[i][k] == '&' ) dp[i][3] = min(dp[i][3],min((ll)(k - 1),(ll)(m - k + 1))); 
			}
		}
	}
	ans = INF;
	for(int i = 1;i <= n;i ++ )
		for(int j = 1;j <= n;j ++ )
			for(int k = 1;k <= n;k ++ )
			{
				if(i != j && i != k && j != k)
				{
					ans = min(ans,dp[i][1] + dp[j][2] + dp[k][3]);
				}
			}
	printf("%d",ans);
	return 0;
} 	


2020.3.31

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章