分石子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.

  

posted @ 2020-12-18 18:16  我微笑不代表我快乐  阅读(128)  评论(0编辑  收藏  举报