Beer Can Game

Beer Can Game

Description
The Beer Can Rows game is played by a single player whose goal is to modify a given arrangement of given beer cans and wooden tokens in the minimum number of moves to obtain an arrangement satisfying a specific condition.
A beer can row is a straight row of objects each of which is either a beer can or a wooden token. Different tokens may have different values, the value of a token is printed on the token. The beginning and the end of each row are clearly marked.
There are two parallel beer can rows prepared for the player by the game master. Typically, the rows are located in some distance from the location of the game master. This configuration is essential for monitoring the progress of the game. The brands of all beer cans which appear in the prepared beer can rows are available. There might be some additional brands available which do not appear in the prepared beer can rows. All brands are available in an unlimited number of cans. All cans of all brands are under the supervision of the game master.
The player begins the game at the game master’s location. From there the player proceeds to the prepared beer can rows where he or she starts to perform moves of the game, one after another.
There are three possible moves a player can perform, Insert can, Expand token, Remove can.
Insert can. The player goes to the game master, asks for a beer can of any available brand and receives it, carries the can back to the beer can rows and inserts it to any row at any place or puts it at the beginning or at the end of any row.
Expand token. The player takes a token from any beer can row and brings it to the game master who exchanges the token for some beer cans. The number of cans is equal to the number printed on the token. The player can choose any mix of brands of the cans. Next, the player carries the cans back to the beer can row from which the token was removed and puts the cans, in any order, into the row at the place of the removed token.
Remove can. The player takes out any can from any of the beer can rows, carries it to the game master and throws it into the dedicated litter bin in his vicinity. Then the player immediately returns to the beer can rows.
The player is obliged to keep each beer can row arranged neatly in a straight line for the entire duration of the game to avoid any uncertainty regarding the order of objects in the row.
The goal of the game is to obtain two identical beer can rows. Two rows are considered to be identical if they contain only beer cans, the number of the cans in both rows is the same and the brand of the k-th can in one row is the same as the brand of the k-th can in the other row, for all values of k in the range from 1 to the length of the rows.
Find the minimum number of moves player needs to finish the Beer Can Rows game.

Input
The input consists of two lines which represent two initial beer can rows. Each line contains only lowercase characters (a – z) and decimal digits 0 – 9. Each character represents one beer can brand, different characters represent different brands. Each brand available in the game is represented by one lowercase character, the character may or may not appear in the input lines. Each digit represents one token, the value of the digit is equal to the value printed on the token. Any input line may contain either only lowercase characters or only decimal digits.
The first input line is at least 1 and at most 10 000 characters long. The second input line is at least 1 and at most 1 000 characters long. There are no more than 100 digits in either of the input lines.
Output
Output a single integer specifying the minimal number of moves a player must perform to obtain two identical rows of cans.

Samples
Input 复制
beer
4
Output
1
Input 复制
beer5ing
4drinking
Output
2

题意:给你两个含有数字的字符串,数字要求必须变成相应数量的字母,且可以变成任意字符,还有两种操作,一是可以删除一个字母,而是可以插入一个字母,问你两个字符串变成相同的字符串最少需要多少操作。

思路:现将数字变成通配符‘*’,然后就成了编辑距离(又称Levenshtein距离,是指两个字串之间,由一个转成另一个所需的最少编辑操作次数。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。)的问题。在这里没有了替换操作;

编辑距离核心代码: link.

		for(int i=1;i<=len1;i++){
        	for(int j=1;j<=len2;j++){
                dp[i][j]=min(dp[i-1][j]+1,dp[i][j-1]+1);
                dp[i][j]=min(dp[i][j],dp[i-1][j-1]+(str1[i-1]!=str2[j-1]));
            }
        }

在这里只需改变一下替换操作,如果字符串a i处的字符等于字符串b j处的字符那么dp[i][j] = min(dp[i-1][j-1],dp[i][j]);


Code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> PI;
const int N = 2e4+10;
string s1,s2;
int res = 0;
int dp[N][2010];
void work(string &t) {
	for(int i=0; i<t.size(); i++) {
		if(t[i]>='0' && t[i]<='9') {
			res++;
			int k = t[i]-'0';
			t.erase(i,1);
			for(int j=0; j<k; j++) {
				t.insert(i,"*");
			}
			if(!k) i--;
		}
	}
	return ;
}
int main() {
	cin>>s1>>s2;
	work(s1);
	work(s2);
	int l1 = s1.size();
	int l2 = s2.size();
	string a = "*"+s1;
	string b = "*"+s2;
	//cout<<a<<" "<<b<<endl;
	for(int i=1; i<=l1; i++) dp[i][0] = i;
	for(int i=1; i<=l2; i++) dp[0][i] = i;
	for(int i=1; i<=l1; i++) {
		for(int j=1; j<=l2; j++) {
			dp[i][j] = min(dp[i-1][j]+1,dp[i][j-1]+1);
			if(a[i]==b[j] || a[i]=='*' || b[j]=='*') dp[i][j] = min(dp[i-1][j-1],dp[i][j]);
			//cout<<i<<" "<<j<<" "<<dp[i][j]<<endl;
		}
	}
	//cout<<res<<" "<<dp[l1][l2]<<endl;
	cout<<dp[l1][l2]+res;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值