zoukankan      html  css  js  c++  java
  • POJ 1011/DFS:子集划分

    问题描述:原有若干sticks,每支stick被分割成若干支,现在要恢复一下。找出这样的子集,使得每个子集的和(plen)相等,并且最小

    算法:排序,遍历所有可能plen

    剪枝:排序后, a[0] a[1] a[2].....a[n-1],如果想从a[i]开始(不包括i)匹配一个数v,如果i+1,i+2......n-1都匹配不成功了,则肯定i+2,i+3....n-1也匹配不成功了,所以从TLE版本做修改后得到AC版本

    TLE:

    #include <iostream>
    #include <algorithm>
    using namespace std;
    #define MAX 64
    int sticks[MAX];
    bool used[MAX];
    int stickNum,plen,n;
    
    bool compare(int a, int b)
    {
        return a > b;    
    }
    //从beginIndex号开始匹配,下一步要匹配matchLen的stick,在此之前已经匹配了hasMatch条stick
    bool dfs(int beginIndex,int matchLen,int hasMatch){
    	//printf("%4d%4d%4d\n",beginIndex,matchLen,hasMatch);
    	if(matchLen==0){
    		hasMatch++;
    		//printf("hasMatch=%d,stickNum=%d\n",hasMatch,stickNum);	
    		if(hasMatch==stickNum){
    			//printf("hasMatch==stickNum\n");	
    			return true;
    		}
    		for(beginIndex=0;used[beginIndex];beginIndex++);
    		//used[beginIndex]=true;
    		//printf("match=%d begin = %d\n",hasMatch,beginIndex);
    		if(dfs(beginIndex,plen,hasMatch))return true;
    		//used[beginIndex]=false;
    		return false;
    	
    	}else{
    		if(beginIndex>n-1)return false;
    		for(int i=beginIndex;i<n;i++){
    			if(used[i])continue;
    			if(sticks[i]>matchLen)continue;
    			if(i>0&&sticks[i]==sticks[i-1]&&!used[i-1])continue;
    			used[i]=true;
    			if(dfs(i+1,matchLen-sticks[i],hasMatch))
    				return true;
    			used[i]=false;
    		}
    	
    	}
    	//printf("end %4d%4d%4d false\n",beginIndex,matchLen,hasMatch);
    	return false;
    
    }
    int main(int argc, char* argv[])
    {
    	
    	int sum = 0;
    	int i;
    	while(scanf("%d",&n)&&n){
    	
    		sum=0;
    		for( i=0;i<n;i++){
    			scanf("%d",&sticks[i]);
    			sum += sticks[i];
    		}
    		bool ok = false;
    		sort(sticks,sticks+n,compare);
    		
    		for(plen=sticks[0];plen<=sum/2;plen++){
    			if(sum%plen==0){
    				
    				//used[0]=true;
    				stickNum = sum/plen;
    				if(dfs(0,plen,0)){
    					ok = true;
    					break;
    				}
    				//used[0]=false;
    			}
    
    		}
    		if(ok){
    			printf("%d\n",plen);
    
    		}else{
    			printf("%d\n",sum);
    		}
    		memset(used,false,sizeof(used));
    	}
    	
    	return 0;
    }

    AC:

    #include <iostream>
    #include <algorithm>
    using namespace std;
    #define MAX 64
    int sticks[MAX];
    bool used[MAX];
    int stickNum,plen,n;
    
    bool compare(int a, int b)
    {
        return a > b;    
    }
    //从beginIndex号开始匹配,下一步要匹配matchLen的stick,在此之前已经匹配了hasMatch条stick
    bool dfs(int beginIndex,int matchLen,int hasMatch){
    	//printf("%4d%4d%4d\n",beginIndex,matchLen,hasMatch);
    	if(matchLen==0){
    		hasMatch++;
    		//printf("hasMatch=%d,stickNum=%d\n",hasMatch,stickNum);	
    		if(hasMatch==stickNum){
    			//printf("hasMatch==stickNum\n");	
    			return true;
    		}
    		for(beginIndex=0;used[beginIndex];beginIndex++);
    		
    		//printf("match=%d begin = %d\n",hasMatch,beginIndex);
    		used[beginIndex]=true;
    		if(dfs(beginIndex+1,plen-sticks[beginIndex],hasMatch))return true;
    		used[beginIndex]=false;
    		return false;
    	
    	}else{
    		if(beginIndex>n-1)return false;
    		for(int i=beginIndex;i<n;i++){
    			if(used[i])continue;
    			if(sticks[i]>matchLen)continue;
    			if(i>0&&sticks[i]==sticks[i-1]&&!used[i-1])continue;
    			used[i]=true;
    			if(dfs(i+1,matchLen-sticks[i],hasMatch))
    				return true;
    			used[i]=false;
    		}
    	
    	}
    	//printf("end %4d%4d%4d false\n",beginIndex,matchLen,hasMatch);
    	return false;
    
    }
    int main(int argc, char* argv[])
    {
    	//freopen("i://in.txt","r",stdin);
    	int sum = 0;
    	int i;
    	while(scanf("%d",&n)&&n){
    		
    		sum=0;
    		for( i=0;i<n;i++){
    			scanf("%d",&sticks[i]);
    			sum += sticks[i];
    		}
    		bool ok = false;
    		sort(sticks,sticks+n,compare);
    		
    		for(plen=sticks[0];plen<=sum/2;plen++){
    			if(sum%plen==0){
    				
    				used[0]=true;
    				stickNum = sum/plen;
    				if(dfs(0,plen-sticks[0],0)){
    					ok = true;
    					break;
    				}
    				used[0]=false;
    			}
    			
    		}
    		if(ok){
    			printf("%d\n",plen);
    			
    		}else{
    			printf("%d\n",sum);
    		}
    		memset(used,false,sizeof(used));
    	}
    	
    	return 0;
    }

    躲猫猫社团团长 http://t.sina.com.cn/coolria

  • 相关阅读:
    Java中二进制数与整型之间的转换
    校招小白机考入坑之从键盘输入java的各种数据类型
    使用flume抓取tomcat的日志文件下沉到kafka消费
    Scala学习笔记之Actor多线程与线程通信的简单例子
    通过流的方式操作hadoop的API
    Windows环境下使用kafka单机模式
    scrapy
    python 虚拟环境
    celery使用
    redis install
  • 原文地址:https://www.cnblogs.com/yangyh/p/2073762.html
Copyright © 2011-2022 走看看