蒟蒻,dp求调
查看原帖
蒟蒻,dp求调
526494
yangyiding楼主2023/8/24 21:01

函数意义:

cticti:char to int 类型转换
itcnitcn:int to char(turn into number) 整型数转化为字符数字
getstr(x,l,r)getstr(x,l,r) :取x在 [l,r][l,r] 间的子串
printprint :递归打印答案(因为先打印左侧,在打印右侧,所以顺序正确)

变量含义:

passwordpassword :待翻译的密码;
dpi,jdp_{i,j} :password的子段[i,j][i,j]是否可以翻译
ans_i,jans\__{i,j}:(在dpi,j==truedp_{i,j} == true的情况下)字段[i,j][i,j]的翻译答案的一种可能的表示方式(即打断点的方式)
注:若 ans_i,j==−1ans\__{i,j} == -1 ,则表示子段 [i,j][i,j] 不需要打断即可翻译
word(map<string,bool>)word(map<string , bool > ) :word[x(string)]word[x(string)] :表示字符串xx(数字串)是否存在至少一种直接翻译(即不打断)的方式。
getwor(map<string,string>)getwor(map<string , string>):getworx(string)getwor_{x(string)} :表示字符串xx(数字串)的一个对应的单词。

实现思路:

dp原则:区间dp,如果区间可以整个翻译,就记ans_i,j=−1ans\__{i,j} = -1,如果不行,就枚举断点midmid,直到找出一个可行的断开的方案,更新dpi,j=truedp_{i,j} = true,并记录ans_i,j=midans\__{i,j}= mid。 最后依照ans_0,length−1ans\__{0,length-1}递归输出。

代码:

#include <stdio.h>
#include <iostream>
#include <string>
#include <map>
#include <cstring>
using namespace std;

bool dp[105][105];
int ans_[105][105];
map<string,bool> word;
map<string , string > getwor;
string password;

int cti(char c)
{
	if('a' <= c && c <= 'c') return 1;
	if(c <= 'f') return 2;
	if(c <= 'i') return 3;
	if(c <= 'l') return 4;
	if(c <= 'n') return 5;
	if(c <= 'q') return 6;
	if(c <= 't') return 7;
	if(c <= 'w') return 8;
	if(c <= 'z') return 9;
	return -1;
}

char itcn(int num)
{
	return (char)(num + 48);
}

inline string getstr(string x,int l,int r)
{
	string res;
	for(int i = l;i<=r;++i)
	{
		res += x[i];
	}
	return res;
}

bool flag = false;

void print(int l,int r)
{
	if(ans_[l][r] == -1)
	{
		if(flag) cout<<" ";
		flag = true;
		cout<<getwor[getstr(password,l,r)];
	}
	else
	{
		print(l,ans_[l][r]);
		print(ans_[l][r]+1,r);
	}
	return ;
}

int main()
{
	memset(dp,0,sizeof(dp));
	memset(ans_,0,sizeof(ans_));
	int n;
	scanf("%d",&n);
//	string password;
	getchar();
	getline(cin,password);
	int length = password.length();
	for(int i=1;i<=n;++i)
	{
		string worder,old_;
		getline(cin,worder);
		int len = worder.length();
		old_ = worder;
		for(int i=0;i<len;++i)
		{
			worder[i] = itcn(cti(worder[i]));
		}
		word[worder] = true;
		getwor[worder] = old_;
	}
//	sum[0] = password[0];
//	for(int i=1;i<length;++i)
//	{
//		char c = password[i];
//		sum[i] = sum[i-1] + c;
//	}
	for(int len = 1;len <= length;++len)
	{
		for(int i=0,j=i+len - 1;j < length;++i,++j)
		{
			if(word[getstr(password,i,j)] == true)
			{
				dp[i][j] = true;
				ans_[i][j] = -1;
				continue;
			}
			for(int mid = i;mid < j;++mid)
			{
				if(dp[i][mid] && dp[mid+1][j])
				{
					dp[i][j] = true;
					ans_[i][j] = mid;
					break;
				}
			}
		}
	}
	if(!dp[0][length-1]) printf("No Solutions!");
	else print(0,length-1);
//	printf("%d",dp[0][length-2]);
	return 0;
}
2023/8/24 21:01
加载中...