CDOJ 1039 Fabricate equation

奇奇怪怪的题,奇奇怪怪的代码,反正问题就在0和9身上,窝已经瞎了
有时间再回来继续搞
官方的题解:
设 Y 为 anan−1an−2···a3a2a1,X 为 bnbn−1bn−2···b3b2b1,X −Y = Z(cncn−1cn−2···c3c2c1)。显然,当 X 每一位都取 9,这样对应的 k 为 n,所以答案一定不大于 Y 的位数。容易发现,有些情况答案可以 更优: 1. 对于第 i 位,如果 bi 没有被 bi−1 借位,且 ai = 0,那么 bi −0 = ci = bi 2. 对于第 i 位,如果 bi 被 bi−1 借位,且 ai = 9,那么 bi −1−9 = ci = bi 对于以上两种情况答案可以少 1。
解法 1(动态规划): 于是我们可以用 dpi,j(0 ≤ j < 2),dpi,0 表示到第 i 位,并且第 i 位没有找 i + 1 位借位,不同的 位数最少是多少;而 dpi,1 则表示到 i 位,第 i 位找 i + 1 位借位,不同位置的最少值。最后的答案 = min(dpn,0,dpn,1 + 1)。状态转移的时候讨论下几种情况,如果第 i−1 位找第 i 位借位,那么对于第 i 位,bi ≤ ai 的时候要借位,bi > ai 不需要;如果第 i−1 位没有找第 i 为借位,那么 bi < ai 的时候要借 位,bi ≥ ai 不需要。各种情况转移的代价稍微思考一下很容易想出来,这里不做过多的介绍。
解法 2(贪心): 1. 如果第 i−1 位可以不找第 i 位借位,并且 ai = 0,属于特殊情况的一种,答案可以少 1,于是我们 任取 bi,并且计第 i 位一定不找第 i + 1 位借位; 2. 如果第 i−1 位一定找第 i 位借位,并且 ai = 9,属于特殊情况的另一种,答案也可以少 1,于是我 们取 bi = 9,并且计第 i 位一定第 i + 1 位借位; 3. 对于其他情况,由于无论如果都不能使答案减小,但是却可以使当前位既可以找第 i + 1 位借位,也 可以不借。 具体实现:从低位开始往高位扫,记录每一位的状态 sta,0 表示一定不借位、1 表示一定借位、2 表示 既可以借位也可以不借位。对于每一位,如果可以是答案减少,那么就贪心的一定选取这种方案;否则将 该位的 sta 调整为 2,更好的服务下一位。 正确性:考虑第 i 位,如果可以使答案 −1,我们选取可以使答案减少的方案 A,设有另外一个方案 B。 那么方案 A 比方案 B 当前答案少 1。考虑接下来可能影响到的第 i + 1 位,最差情况下,就是方案 A 在 i + 1 位不能使答案 −1,而方案 B 可以。于是,这个时候两个方案的答案扯平了,但是之后的答案仅与第 i + 1 的 sta 有关,而方案 A 一定可以将 sta 调整为 2,所以一定不会比方案 B 差,所以可以保证我们这 样贪心,一定不存在更好的方案,即这样一定是最优的。

去年的代码(队友想的):
#include <stdio.h>
#include <string.h>
int main()
{
	long long int y;
	int i=0,k=0,t=0,n;
	char yy[20];
	scanf("%lld",&y);
	sprintf(yy,"%lld",y);
	n=strlen(yy);
	if(yy[0]=='9') yy[0]='1';
	if(yy[n-1]=='9') yy[n-1]='1';
	for(i=2;i<n-2;i++) 
		if(yy[i]=='0'&&yy[i+1]=='9'&&yy[i-1]=='9'&&yy[i-2]!='0'&&yy[i-2]!='0') yy[i]='1';
	for(i=0;i<n;i++)
	{
		if(yy[i]=='0'&&yy[i-1]=='9') yy[i-1]='1';
		if(yy[i]=='0'&&yy[i+1]=='9') yy[i+1]='1';
	}
	for(i=0;i<n;i++)
		if(yy[i]=='0'||yy[i]=='9') t++;
	k=n-t;
	printf("%d",k);
	return 0; 
 }

今年的代码(我xjb乱搞的):
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
char str[22];
int n;
int ans;
int main()
{
	//freopen("input.txt", "r", stdin);
	scanf("%s", str);
	n = strlen(str);
	ans = n;
	for (int i = 0; i < n; ++i)
	{
		if (i == 0&&str[i]=='9'&&str[i+1]=='0')
		{
			--ans; ++i;
			continue;
		}
		if (i == n - 2 && str[i] == '0'&&str[i + 1] == '9')
		{
			--ans; ++i;
			continue;
		}
		if (i > 0 && i < n - 2 && str[i] == '0'&&str[i + 1] == '9'&&str[i + 2] == '0')
		{
			ans -= 2;
			i += 2;
			continue;
		}
		if (str[i] == '0')
		{
			if (i == 0 || str[i - 1] != '9')
				--ans;
		}
		else if (str[i] == '9')
		{
			if (i > 0 && str[i - 1] != '0')
				--ans;
			if (i == n - 1)
				++ans;
		}
	}
	printf("%d\n", ans);
	//system("pause");
	//while (1);
	return 0;
}

讲道理,如果这两份代码搞对拍的话,有的情况应该会出不一样的答案,可是,管他呢

你可能感兴趣的:(CDOJ 1039 Fabricate equation)