zoj 1832 file fragmentation

题目其实不算难。可以先把片段按长度排序,对于长度相同的则再按字符串比较,这样相同的片段就会在一起,从而可以大大减少不必要的搜索。

几次提交得到WA,于是自己构造5000组测试用例结果显示没有错。以为是zoj数据太刁钻,调了几个小时还是WA,最后终于发现是输入输出格式问题。。。坑爹!格式控制仍然是心中的痛哎

看上去很费时,其实搜索速度很快,提交通过时间0ms,内存276KB。

#include<fstream>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include "m_debug.h"
using namespace std;

string frag[300];
bool used[300];

string res; //result string
int len; //result string's length
int n; //片段总数量

class Less{
public:
	bool operator()(const string &s1,const string &s2){ 
		if(s1.length()<s2.length()) return true;
		else if(s1.length()==s2.length() && s1<s2) return true;
		else return false;
	}
};

bool solve(int spos,int epos){
	
	if(spos>=epos){
		for(int i=epos;i<n;i++) if(used[i]==false) return false;
		return true;
	}

	if(used[spos]){ while(spos<epos && used[spos]) spos++; return solve(spos,epos); } //frag[spos]在此前可能已经配对

	used[spos] = true;

	if(res==""){ 
		for(int i=epos;frag[i].length()==frag[n-1].length();i--){
			
			if(i<epos && frag[i]==frag[i+1]) continue; //剪枝,避免重复搜索

			res = frag[spos] + frag[i];
			used[i] = true; //暂时占用frag[i]
			if(solve(spos+1,epos)) return true;
			else{
				res = frag[i] + frag[spos];
				if(res!=frag[spos]+frag[i] && solve(spos+1,epos)) return true;
				else used[i] = false; //释放frag[i]
			}
		}
	}
	else{
		while(spos<epos && frag[spos].length()+frag[epos].length()>len) epos--;
		
		if(spos==epos) return false;
			
		for(int i=epos;i>spos&&frag[i].length()==frag[epos].length();i--){

			if(used[i] || (res!=frag[spos]+frag[i] && res!=frag[i]+frag[spos])) continue; //frag[i]被占用或frag[i]不能与frag[spos]配对
            //frag[i]能与frag[spos]配对,继续后续匹配
			used[i] = true;
			if(solve(spos+1,epos)) return true;
			else{
				used[i] = false;  //虽然frag[i]能与frag[spos]匹配,但存在失败的后续匹配,也是不行
				while(i>spos+1 && frag[i]==frag[i-1]) i--;  //跳过与frag[i]相同的片段,避免重复搜索
			}
		}

		used[spos] = false; //释放frag[spos]
		return false;  //没有一个满足条件的frag能与frag[spos]配对,表明当前的匹配方式是错误的
	}
}
	
int main(){
	
    //ifstream cin("input.txt");
	int i;
    
	while(getline(cin,frag[0])){
		i=1;
		while(getline(cin,frag[i])){
			if(frag[i].size()==0) break;
			else i++;
		}		
		sort(frag,frag+i,Less()); //按按片段长度进行排序
        len = frag[0].length() + frag[i-1].length(); //完整bit的长度
    
		n = i;
		solve(0,n-1);
		cout<<res<<endl;
		
		res = "";
        for(int j=0;j<i;j++) used[j] = false;
	}
	return 0;
}

		




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值