zoukankan      html  css  js  c++  java
  • vijos1037搭建双塔(一维背包问题)

    描述

    2001年9月11日,一场突发的灾难将纽约世界贸易中心大厦夷为平地,Mr. F曾亲眼目睹了这次灾难。为了纪念“9?11”事件,Mr. F决定自己用水晶来搭建一座双塔。

    Mr. F有N块水晶,每块水晶有一个高度,他想用这N块水晶搭建两座有同样高度的塔,使他们成为一座双塔,Mr. F可以从这N块水晶中任取M(1≤M≤N)块来搭建。但是他不知道能否使两座塔有同样的高度,也不知道如果能搭建成一座双塔,这座双塔的最大高度是多少。所以他来请你帮忙。

    给定水晶的数量N(1≤N≤100)和每块水晶的高度Hi(N块水晶高度的总和不超过2000),你的任务是判断Mr. F能否用这些水晶搭建成一座双塔(两座塔有同样的高度),如果能,则输出所能搭建的双塔的最大高度,否则输出“Impossible”。

    格式

    输入格式

    输入的第一行为一个数N,表示水晶的数量。第二行为N个数,第i个数表示第i个水晶的高度。

    输出格式

    输出仅包含一行,如果能搭成一座双塔,则输出双塔的最大高度,否则输出一个字符串“Impossible”。

    样例1

    样例输入1[复制]

    5
    1 3 4 5 2

    样例输出1[复制]

    7

    来源

    某校NOIP模拟题

    很容易地敲出了暴力代码

    j=dfs(l1,l2,cur)
    {
    	if cur==n+1
    		if l1==l2 then record(l1)
    		exit
    	dfs(l1+h[cur],l2,cur+1)
    	dfs(l1,l2+h[cur],cur+1)
    	dfs(l1,l2,cur+1)
    }

    于是自己愚蠢地写了一个动规代码

    dp()
    	for(i->1 to n)
    		for(j->tot/2 to h[i])
    			f[i][j]=f[i-1][j]
    			if(f[i-1][j-h[i]])
    				if f[i-1][j] then record(j)
    				f[i][j]=1

    然而思路是错的,得分:30。

    测试数据 #0: Accepted, time = 0 ms, mem = 516 KiB, score = 10

    测试数据 #1: WrongAnswer, time = 0 ms, mem = 516 KiB, score = 0

    测试数据 #2: WrongAnswer, time = 15 ms, mem = 516 KiB, score = 0

    测试数据 #3: WrongAnswer, time = 0 ms, mem = 512 KiB, score = 0

    测试数据 #4: Accepted, time = 0 ms, mem = 520 KiB, score = 10

    测试数据 #5: WrongAnswer, time = 0 ms, mem = 516 KiB, score = 0

    测试数据 #6: WrongAnswer, time = 0 ms, mem = 516 KiB, score = 0

    测试数据 #7: Accepted, time = 0 ms, mem = 516 KiB, score = 10

    测试数据 #8: WrongAnswer, time = 0 ms, mem = 516 KiB, score = 0

    测试数据 #9: WrongAnswer, time = 0 ms, mem = 512 KiB, score = 0

    WrongAnswer, time = 15 ms, mem = 520 KiB, score = 30

    标准解法:令f[i][j]为前i块水晶搭成的双塔高度差为j时,最矮的塔的高度的max值。

    为转移f[i][j],我们先列出一下策略:

    1.不选该水晶块,此时直接继承,f[i][j]->f[i-1][j],此时的高度不变

    2.选择该水晶块,放在原本就高的塔上,f[i][j]=f[i-1][j-h[i]]

    3.选择该水晶块,放在原本就小的塔上,则:

                   (1.小的还是小的,那么f[i][j]=f[i-1][j+h[i]]+h[i]

                   (2.小的成为了大的,那么f[i][j]=f[i-1][h[i]-j]+h[i]-j

    Qed!

    代码:

    Accepted

     
    100
    0 536 ksq2013 C++ 2016-08-18 22:36:20
    #include<stdio.h>
    #include<stdlib.h>
    using namespace std;
    inline int mx(int x,int y)
    {
        if(x>y)return x;
        return y;
    }
    int f[3][2001];
    int n,h[201],tot;
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&h[i]);
            tot+=h[i];
        }
        for(int i=0;i<=1;i++)
            for(int j=1;j<=tot;j++)
                f[i][j]=-0x3f3f3f3f;
        int t=1;
        for(int i=1;i<=n;i++){
            t^=1;
            for(int j=h[i];j<=tot;j++)
                f[t][j]=mx(f[t][j],f[1^t][j-h[i]]);
            for(int j=0;j<=tot-h[i];j++)
                f[t][j]=mx(f[t][j],f[1^t][j+h[i]]+h[i]);
            for(int j=0;j<h[i];j++)
                f[t][j]=mx(f[t][j],f[1^t][h[i]-j]+h[i]-j);
            for(int j=0;j<=tot;j++)
                f[1^t][j]=f[t][j];
        }
        if(f[1^t][0])
            printf("%d
    ",f[1^t][0]);
        else puts("Impossible");
        return 0;
    }

     其实这样写更直观

    #include<iostream>
    using namespace std;
    int n,h[1001],tot;
    bool f[1001][1001];
    int main(){
        ios::sync_with_stdio(false);
        cin>>n;
        for(int i=1;i<=n;i++)
            cin>>h[i],
            tot+=h[i];
        f[0][0]=1;
        tot>>=1;
        for(int k=1;k<=n;k++)
            for(int i=tot;i>=0;i--)
                for(int j=tot;j>=0;j--){
                 if(i-h[k]>=0&&f[i-h[k]][j])f[i][j]=1;
                 else if(j-h[k]>=0&&f[i][j-h[k]])f[i][j]=1;
                }
        for(int i=tot;i>=1;i--)
            if(f[i][i]){
                cout<<i<<endl;
                return 0;
            }
        cout<<"Impossible"<<endl;
        return 0;
    }
  • 相关阅读:
    List里如何剔除相同的对象?
    Collections工具类中的sort方法如何比较元素?
    TreeMap和TreeSet在排序时如何比较元素?
    Map的实现类中,哪些是有序的,哪些是无序的,如何保证其有序性?
    LinkedHashMap、LinkedHashSet、LinkedList哪个最适合当作Stack使用?
    ArrayList与LinkedList哪个插入性能高?
    HashSet和HashMap有什么区别?
    HashSet实现原理是什么?有什么特点?
    TreeSet的原理是什么?使用需要注意什么?
    Java中已经数组类型,为什么还要提供集合?
  • 原文地址:https://www.cnblogs.com/keshuqi/p/5957701.html
Copyright © 2011-2022 走看看