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

浙公网安备 33010602011771号