数字拼接

给出N个数字(2=<N<=9),每个数字长度是2-6位,每一位是1到4,如果某个数字尾数和其他的数字的数头相同,即可连成一个新的数字,

   如123,234可以连成1234,连成的新的数字可以和其他未使用过的数字再按照规则连接成为新的数字

  如:123,141,234,可以连成1234,14123和141234

注意:case 里面可能只有一部分数字可以连接222 222 可以形成22222,也可以形成2222

求能够连接的最大数字是几位??


input.txt

5
3
123
141
234
2
24
123
4
343
2433
2213
3333
8
434121
441
4234
223142
23413
14342
224
234
9
221111
212111
122111
121232
211112
122112
211111
211121
121122



程序:

#include <stdio.h>
#include <stdlib.h>

#define SIZE 9
#define MAXLEN 6

int data[SIZE][MAXLEN];
int numberLen[SIZE];
int overlapLen[SIZE+1][SIZE+1];

void IToA(int N,int row){//数字转数组,并记录长度,
	int tmp = N;
	int i = 0;
	while(tmp){
		i++;
		tmp/=10;
	}
	numberLen[row] = i;
	tmp = N;
	for(int j = i-1;j>= 0;j--){
		data[row][j] = tmp % 10;
		tmp /= 10;
	}
}

void getOverlapLen(int i,int j){//计算两个数字的最小重叠长度
	for(int len = 1;len<=numberLen[i]&& len <= numberLen[j];len++){
		int match =1;
		for(int m = numberLen[i] - len,  n=0;m<numberLen[i] && n < numberLen[j];m++,n++){
			if(data[i][m] != data[j][n]){
				match = 0;
				break;
			}
		}
		if(match){
			overlapLen[i][j] = len;
			break;
		}
	}
}

int maxLen = 0;
int used[SIZE];

void getMaxLen(int step,int numbers,int curLen,int remainingLen,int preNumber){//getMaxLen(0,N,0,totalLen,SIZE);
	if(step == numbers){//出口
		return;
	}
	if(curLen + remainingLen - numbers + step +1 <= maxLen){//预测长度剪枝
		return;
	}

	for(int i = 0;i<numbers;i++){
		if(!used[i]){
			used[i] = 1;
			int tmpLen = curLen;

			if(overlapLen[i][preNumber] == 0 && step != 0){//只处理连接成功的情况
				used[i] = 0;//注意占位及恢复
				continue;
			}

			curLen += numberLen[i] - overlapLen[i][preNumber];
			if(maxLen < curLen){
				maxLen = curLen;
			}
			getMaxLen(step + 1,numbers,curLen,remainingLen - numberLen[i],i);

			used[i] = 0;
			curLen = tmpLen;
		}
	}
}

void main(){
	freopen("input.txt","r",stdin);
	int nTc;
	scanf("%d",&nTc);
	for(int tc = 0;tc < nTc; tc++){
		int N;
		scanf("%d",&N);
		maxLen = 0;
		for(int i = 0;i<N;i++){
			used[i] = 0;
			for(int j = 0;j<N;j++){
				data[i][j] = 0;
				overlapLen[i][j] = 0;
			}
		}

		int temp;
		int totalLen = 0;
		for(int i = 0;i<N;i++){
			scanf("%d\n",&temp);
			IToA(temp,i);
			totalLen += numberLen[i];
		}

		for(int i =0;i<N;i++){
			for(int j = 0;j<N;j++){
				if(i != j){
					getOverlapLen(i,j);
				}
			}
		}

		getMaxLen(0,N,0,totalLen,SIZE);
		printf("%d\n",maxLen);
	}
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值