• 分石子2



    有N堆石子。现将它们分成两个组A,B。 每组有N/2堆石子 要求两个组的石子数相接近越好。

    输入
    每组测试数据第一行一个整数n,n为偶数且小于100 第二行n个整数分别给出每堆石子的石子数字,所有石子总和不超过2000

    输出
    输出A,B两组的最小差值。

    样例
    输入复制
    6
    7 9 2 6 4 2
    输出复制
    0

    三维的,注意第二个循环一定要逆循环。新算出来的状态不能参加后面的运算。

    #include<bits/stdc++.h>
    using namespace std;
    bool f[200][101][2001];
    int n,a[101];
    int abbs(int x,int y)
    {
    if(x-y>0) return x-y;
    else return y-x;
    }
    int main()
    {
    cin>>n;
    int sum=0;
    for(int i=1;i<=n;i++)
    {
    scanf("%d",&a[i]);
    sum+=a[i];
    }
    memset(f,0,sizeof(f));
    f[0][0][0]=1;
    for(int i=1;i<=n;i++)
    for(int j=n;j>=0;j--) //所使用的数字个数 
    // for(int k=2000;k>=0;k--)
    // for (int j=0;j<=n;j++)
    for (int k=0;k<=2000;k++) //构成的总和 
    {
    f[i][j][k]=f[i-1][j][k];
    if(f[i-1][j][k]==1)
        f[i][j+1][k+a[i]]=1;
    }
    int ans=sum;
    for(int i=0;i<=sum;i++)
    if(f[n][n/2][i]==1)
    {
    //	cout<<i<<" is "<<endl;
    if(ans>abbs(i,sum-i))
    {
    ans=abbs(i,sum-i);
    }
    }
    cout<<ans<<endl;
    return 0;
    }
    

      

    #include<bits/stdc++.h>
    using namespace std;
    bool f[200][101][2001];
    int n,a[101];
    int abbs(int x,int y)
    {
    if(x-y>0) return x-y;
    else return y-x;
    }
    int main()
    {
    cin>>n;
    int sum=0;
    for(int i=1;i<=n;i++)
    {
    scanf("%d",&a[i]);
    sum+=a[i];
    }
    memset(f,0,sizeof(f));
    f[0][0][0]=1;
    for(int i=1;i<=n;i++)
    for(int k=2000;k>=0;k--) //所构成的总和 
    for(int j=0;j<=n;j++) //所使用的数字个数 
    {
    f[i][j][k]=f[i-1][j][k];
    if(f[i-1][j][k]==1)
        f[i][j+1][k+a[i]]=1;
    }
    int ans=sum;
    for(int i=0;i<=sum;i++)
    if(f[n][n/2][i]==1)
    {
    //	cout<<i<<" is "<<endl;
    if(ans>abbs(i,sum-i))
    {
    ans=abbs(i,sum-i);
    }
    }
    cout<<ans<<endl;
    return 0;
    }
    

      二维的程序

    #include<bits/stdc++.h>
    using namespace std;
    bool f[101][2001];
    int n,a[101];
    int abbs(int x,int y)
    {
    if(x-y>0) return x-y;
    else return y-x;
    }
    int main()
    {
    cin>>n;
    int sum=0;
    for(int i=1;i<=n;i++)
    {
    scanf("%d",&a[i]);
    sum+=a[i];
    }
    memset(f,0,sizeof(f));
    f[0][0]=1;
    for(int i=1;i<=n;i++)
    for(int k=2000;k>=0;k--)
    for(int j=n;j>=0;j--)
        if(f[j][k]==1)
             f[j+1][k+a[i]]=1;
    int ans=sum;
    for(int i=0;i<=sum;i++)
    if(f[n/2][i]==1)
    {
    if(ans>abbs(i,sum-i))
    {
    ans=abbs(i,sum-i);
    }
    }
    cout<<ans<<endl;
    return 0;
    }
    

      

    分石子3
    给你N个数字,当然不是每个数字你均需要用到,现将这些数字分成两部份
    其总和是相等的。问这个值最大能到多少?如果不能分成相等的两份就输出"Sorry"

    输入
    第一个数字N(100以内)代表数字的个数.
    接下来N个数代表每个数字.所有数字的总和不超过2000

    输出
    如题所示

    样例
    输入复制
    4
    11 11 11 11
    输出复制
    22

    #include<bits/stdc++.h>
    using namespace std;
    int main()
    { int n,s[101],f[111][3001],sum=0;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    scanf("%d",&s[i]),sum+=s[i];
    sum/=2;
    memset(f,-1,sizeof(f));
    f[0][0]=0;
    //f[i,j]表示用前i个数字,两塔高度差为j时,矮的塔的高多为多少
    for(int i=1;i<=n;i++)//枚举数字,可以不选,所以从0开始
    for(int j=0;j<=sum;j++) //枚举两者的高度差
    if(f[i-1][j]>=0)
    {
    f[i][j]=max(f[i][j],f[i-1][j]);
    //这个数字不用
    f[i][s[i]+j]=max(f[i][s[i]+j],f[i-1][j]);
    //将数字放在高塔上,高度差增加,矮塔高度不变
    if(s[i]>j)//将数字放在矮塔上,高矮关系发生改变 ,新矮塔高度增加j
    f[i][s[i]-j]=max(f[i][s[i]-j],j+f[i-1][j]);
    else
    //将数字放在矮塔上,高矮关系不变,原矮塔高度增加s[i]
    f[i][j-s[i]]=max(f[i-1][j]+s[i],f[i][j-s[i]]); }
    if(f[n][0])
    printf("%d",f[n][0]);
    else
    printf("Sorry");
    } 
    

      

    1778506  	2006-04-19 14:42:00  	Accepted 	2059 	FPC  	00:00.17  	424K  	我微笑不代表我快乐
    
    program zju2059;
    var h,s:array[0..100] of integer;
        f,f1:array[0..2000] of integer;
        n,i,j:longint;
    begin
    while true do
    begin
         read(n);
         if n=-1 then halt;
         s[0]:=0;
         for i:=1 to n do
              begin
                       read(h[i]);
                       s[i]:=s[i-1]+h[i];
              end;
         for j:=1 to s[n] do
             f1[j]:=-1;
         f1[0]:=0;
         f1[h[1]]:=h[1];
    //f1[i]代表二个Twin之间高度差为i时,较高的Twin的高度为F1[i]
         f:=f1;
         for i:=1 to n-1 do
         begin
               for j:=0 to s[i] do
                   if f1[j]>-1 then
                       begin
                             if f1[j]+h[i+1]>f[j+h[i+1]] then 
    //将当前Stone放到二个Twin中较高的那个上面,这个条件是不能去掉的!
                                 f[j+h[i+1]]:=f1[j]+h[i+1];
                             if h[i+1]<=j then
    //将当前的Stone放到较矮的Twin上去,这样要分二种情况讨论一下,因为放上去后,有可能会影响
    //到二个Twin之间的高矮关系,当h[i+1]<j时,说明放到矮的Twin上,高矮关系不会变化
                                begin
                                        if f1[j]>f[j-h[i+1]] then
                                             f[j-h[i+1]]:=f1[j]
                                end
                             else
                                    if f1[j]-j+h[i+1]>f[h[i+1]-j] then
    //f1[j]-j代表从前矮Twin的高度,因为f1[j]代表高度差为J时,高Twin的高度,于是矮Twin的高度就应该为
    //f1[j]-j,现在将Stone放到矮Twin上,并且放上去后,影响了高矮Twin之间的关系,从前高的变成了矮的
    //矮的变成了高的.于是放上去后新的高Twin的高度为F1[j]-j+H[i+1].
                                       f[h[i+1]-j]:=f1[j]-j+h[i+1]
                      end;
                f1:=f;
       end;
       if n=0 then 
             writeln('Sorry')
       else
             if f[0]>0 then
                 writeln(f[0])
             else
                      writeln('Sorry');
    end;
    end.
    

      

  • 相关阅读:
    Mongodb在Linux下的安装和启动和配置
    Java线程--Exchanger使用
    Java线程--Phaser使用
    Java线程--CyclicBarrier使用
    Java线程--CountDownLatch使用
    Java线程状态介绍
    Java8 Stream 的一些操作和介绍
    Java正则
    Linux curl命令进行网络请求
    Netty入门使用教程
  • 原文地址:https://www.cnblogs.com/cutemush/p/14156326.html
Copyright © 2020-2023  润新知