_Yxz_ 2022-08-12 14:18 采纳率: 100%
浏览 60
已结题

POJ1011洛谷4个点TLE

POJ1011问题TLE,求大老回答


#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string.h>
using namespace std;

const int maxn=100+10;
int n,mx,sum,nl,k;
int a[maxn],nxt[maxn];
bool vis[maxn];
inline bool cmp(int x1,int y1){
    return x1>y1;
} 
inline bool dfs(int len,int x,int num){
    if(num==k)return true;
    for(int i=x;i<=k;i++){
        if(vis[i]||(i>1&&!vis[i-1]&&!(a[i]^a[i-1])))continue;
        vis[i]=true;
        if(len+a[i]<nl){
            if(dfs(len+a[i],i+1,num+1))return true;
        }
        else if(len+a[i]==nl){
            if(dfs(0,1,num+1))return true;
        }
        vis[i]=false;
        if(len==0)break;
    }
    return false;
}
int main(){
    while(~scanf("%d",&n)){
        if(n==0)break;
        sum=0,mx=0,k=0;
        for(int i=1;i<=n;i++){
            int b;
            scanf("%d",&b);
            if(b>50||b==0)continue;
            a[++k]=b;
            sum+=b;
            mx=max(mx,b);
        }
        //printf("mx %d sum %d\n",mx,sum);
        sort(a+1,a+k+1,cmp);
        /*
        for(int i=1;i<=n;i++)printf("%d ",a[i]);
        printf("\n");
        */
        /*
        memset(nxt,0,sizeof(nxt));
        nxt[k]=k;
        for(int i=k-1;i>=1;i--){
            if(a[i]==a[i+1])nxt[i]=nxt[i+1];
            else nxt[i]=i;
        }
        */
        int ans=0;
        for(int i=mx;i<=(sum>>1)+1;i++){
            if(sum%i!=0)continue;
            nl=i;
            memset(vis,false,sizeof(vis));
            if(dfs(0,1,0)){
                ans=nl;
                break;
            }
        }
        if(ans==0)ans=sum;
        printf("%d\n",ans);
    }
    return 0;
} 
  • 写回答

3条回答

  • 兔子递归 2022-08-14 09:59
    关注

    你看一下这个代码行不行

    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Scanner;
     
    /**
     * created by 吴家俊 on 2019/9/17.
     */
    public class Main{
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            int count = scanner.nextInt();
            ArrayList<Integer> list = new ArrayList();
            int sum;
            while (count != 0) {
                sum = 0;
                for (int i = 0; i < count; i++) {
                    int k = scanner.nextInt();
                    list.add(k);
                    sum += k;
                }
                Bar bar = new Bar(list, sum);
                bar.inputResult();
                count = scanner.nextInt();
                //清空list
                list.clear();
            }
        }
    }
     
    class Bar {
        private ArrayList<Integer> list;//存储被切后各个棒的长度
        private int[] visit; //访问数组标记某个数是否被使用过 0未使用 1使用
        private int len; //预测最初每个棒的长度
        private int n; //最初棒的个数
        private int sum; //棒的总长度
        private boolean flag; //标记是否得出结果
     
        public Bar(ArrayList<Integer> list, int sum) {
            this.list = list;
            this.sum = sum;
            Collections.sort(list);
            Collections.reverse(list); //按棒长降序排序
        }
     
        private void init() {
            visit = new int[list.size()];
            flag = false;
        }
     
        public void inputResult() {
            for (int i = list.get(0); i <= sum; i++) { //1、缩小len的取值范围
                if (i == sum) {
                    System.out.println(i);
                } else if (sum % i == 0) { //2、再次缩小len的取值范围
                    n = sum / i;
                    len = i;
                    init();
                    dfs(0, len, 0);
                    if (flag) {
                        break;
                    }
                }
            }
        }
     
        /**
         * @param index 遍历的起始下标
         * @param l     当前剩余长度 为0时 表示凑成了一个原先的棒
         * @param now   当前已经凑成的棒的根数 为n时 表示得到解
         */
        private void dfs(int index, int l, int now) {
            if (flag) return;
            if (now >= n) {
                flag = true;
                System.out.println(len);
                return;
            }
            for (int i = index; i < visit.length; i++) {
                if (visit[i] == 0 && l - list.get(i) >= 0) {
                    visit[i] = 1; //标记已访问
                    if (l - list.get(i) == 0) { //凑成了一根棒
                        dfs(0, len, now + 1); //开始寻找下一个棒的起点
                    } else {
                        dfs(index + 1, l - list.get(i), now);
                    }
                    visit[i] = 0; //还原
                    if (flag) return;
                    if (l == len) return; //3、之前的决策有问题,回退到上一根棒的拼凑过程
                    while (i + 1 < visit.length && list.get(i + 1) == list.get(i)) {//4、该点失败后,后面相同的点不用再尝试
                        i++;
                    }
                }
            }
        }
    }
    
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 8月24日
  • 已采纳回答 8月16日
  • 创建了问题 8月12日

悬赏问题

  • ¥15 有偿求码,CNN+LSTM实现单通道脑电信号EEG的睡眠分期评估
  • ¥15 没有证书,nginx怎么反向代理到只能接受https的公网网站
  • ¥50 成都蓉城足球俱乐部小程序抢票
  • ¥15 yolov7训练自己的数据集
  • ¥15 esp8266与51单片机连接问题(标签-单片机|关键词-串口)(相关搜索:51单片机|单片机|测试代码)
  • ¥15 电力市场出清matlab yalmip kkt 双层优化问题
  • ¥30 ros小车路径规划实现不了,如何解决?(操作系统-ubuntu)
  • ¥20 matlab yalmip kkt 双层优化问题
  • ¥15 如何在3D高斯飞溅的渲染的场景中获得一个可控的旋转物体
  • ¥88 实在没有想法,需要个思路