• uva 10317 Equating Equations


    题目链接:

    http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=457&page=show_problem&problem=1258

    1. 先对等式进行移项,假设原来为1 + 2 = 4 - 5 + 6,那么移动之后就变为了 1 + 2 - 4 + 5 + 6 = 0. 并计算出所有数字之和sum,和等式左边中的正数个数plusNum

    2. 然后就演变成了“从n个数中选取总和为sum/2的plusNum个数字组成正数部分”,因为如果等式成立,那么所有正数之和与所有负数之和的绝对值一定是相等的。正样的话,对于每个数,要么取,要么不取,复杂度就变为了 2^16

    3. 减枝: 1) 每次递归时,如果当前值加上要选的那个数之和大于sum/2,则不选

                     2) 如果所有数字之和为奇数,那么直接no solution。这个优化相当大,直接从1.9s降到了0.08s。不过rank第一的神牛的0.02s真不知道怎么跑出来的 Orz..



    #include<cstdio>
    #include<cstring>
    
    const int maxn = 1000;
    char str[10000];
    char sigma[maxn];
    bool vis[maxn];
    int  num[maxn], ans[maxn], n, idx;
    int  plus[maxn], leftNum, plusNum, sum;
    
    
    inline void read(){
    	idx = 1;
    	sscanf(str, "%d", &num[0]);
    	sum = num[0];
        int len = strlen(str);
    	for(int i=1; i<len; ++i){
    	    if(str[i]=='+' || str[i]=='-' || str[i]=='=') {
    		    if(str[i] == '=') 
                    leftNum = idx;
    		    sigma[idx] = str[i];
    		    sscanf(str+i+1, "%d", &num[idx]);
    	    	sum += num[idx++];
    	    }
    
    	}
        // 把等式全部移到左边后,计算有多少个加号
        plusNum = 1;
        for(int i=1; i<idx; ++i){
            if(i<leftNum && sigma[i] == '+'){ 
                ++plusNum;
            } else if(i>leftNum && sigma[i] == '-') 
                ++plusNum;
        
        }
    }
    
    bool dfs(int cur, int pos, int tot){
        if(plusNum-cur > idx-pos)
            return false;
        if(cur == plusNum){
            if(tot*2 == sum) return true;
            return false;
    
        }
        if(pos<idx && (tot+num[pos])*2 <= sum){
            vis[pos] = true;
            plus[cur] = num[pos];
            if(dfs(cur+1, pos+1, tot+num[pos])) 
                return true;
    
        }
        vis[pos] = false;
        if(pos<idx && dfs(cur, pos+1, tot))
            return true;
        return false;
    
    }
    
    inline void solve(){
        //注意减枝!如果sum为奇数那么直接输出no solution
        memset(vis, 0, sizeof(vis));
        if((sum&1)==0 && dfs(0, 0, 0)){ 
            int id=1;
            ans[0] = plus[0];
            for(int i=1; i<idx; ++i){
                if(i<leftNum && sigma[i]=='+') {
                    ans[i] = plus[id++];
                } else if(i>leftNum && sigma[i]=='-'){
                    ans[i] = plus[id++];
                }
    
            }
            int k=1;
            for(int i=0; i<idx; ++i)if(!vis[i]){
                while(k<leftNum && sigma[k]=='+' && k<idx) ++k;
                while(k>leftNum && sigma[k]=='-' && k<idx) ++k;
                ans[k++] = num[i];
    
            }
            printf("%d", ans[0]);
            for(int i=1; i<idx; ++i)
                 if(i==leftNum) printf(" = %d",ans[i]);
                 else printf(" %c %d", sigma[i], ans[i]);
            puts("");
    
        }else{
            puts("no solution");
        
        }
    
    }
    
    int main(){
    
        while(gets(str)){
            read();
            solve();
        }
    
        return 0;
    }


  • 相关阅读:
    关于论文绘图的一些拾遗
    在线word论文生成的方法
    用LyX写中文幻灯片
    关于KO信息
    关于中文期刊LaTeX的CCT相关
    Android NDK and OpenCV Development With Android Studio
    android上的JAVA8:使用retrolambda
    WebSocket学习笔记——无痛入门
    html5利用websocket完成的推送功能
    [Android]通过JNI访问并操作Bitmap的元素,支持RGB565和ARGB8888
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/2978372.html
Copyright © 2020-2023  润新知