265 条题解
-
13
PowderHan LV 10 @ 7 年前
-
47 年前@
简单说一下我的思路 参考01背包
每个城堡都做一遍 找出可以达到的高度
之后再用数组&操作找出可以共同达到的高度
之后从10000(城堡可能达到的最大高度)向下循环输出第一个可以共同达到的高度即可
ps:由于无法完成要输出0,所以最后要确保0可以正常输出 -
16 年前@
-
18 年前@
还是
01
背包问题,相当于每个城堡都做一次,看看那个状态是每个城堡都能到达的。 -
04 年前@
-
07 年前@
n个城堡单独背包,记录可能的高度。
-
08 年前@
-
08 年前@
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
bool judge[101][10004];
int high[101][10004];
int num[101];
int main()
{
int n,maxn=-9999999;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int sum=0;
for(;
{
scanf("%d",&high[i][++num[i]]);
if(high[i][num[i]]==-1)break;
sum+=high[i][num[i]];
}
num[i]--;judge[i][0]=true;
if(sum>=maxn)maxn=sum;
judge[i][sum]=true;
for(int j=1;j<=num[i];j++)
{
for(int k=sum;k>=0;k--)
judge[i][k]=(judge[i][k]||judge[i][k-high[i][j]]);
}
}
for(int i=maxn;i>=0;i--)
{
for(int j=1;j<=n;j++)
{
if(!judge[j][i])break;
if(j==n)
{
printf("%d",i);return 0;
}
}
}
} -
08 年前@
练习位运算不错
```
#include <cstdio>
#include <cstring>
#include <iostream>
#include <bitset>
#define rep(x,to) for(int x=0;x<(to);x++)
#define repn(x,to) for(int x=1;x<=(to);x++)
using namespace std;
const int mod=1e9+7;
bitset<10005> bs[105];
int main()
{
#ifdef LOCAL
freopen("in","r",stdin);
#endif // LOCAL
int n,x,ans=0;
scanf("%d",&n);
rep(i,n)
{
bs[i][0]=1;
for(;
{
scanf("%d",&x);
//cout<<x<<endl;
if(x==-1)break;
bs[i]|=bs[i]<<x;
}
}
//rep(i,n)cout<<bs[i]<<endl;
repn(i,n)bs[i]&=bs[i-1];
rep(i,(int)bs[n-1].size())if(bs[n-1][i])ans=max(ans,i);
//cout<<bs[0]<<endl;
cout<<ans<<endl;
return 0;
} -
08 年前@
-
08 年前@
#include<cstdio>
int f[10001],g[10001],n,h;
int main()
{
scanf("%d",&n);
memset(f,true,sizeof(f));
while(n--)
{
g[0]=true;
for(int i=1;i<=10000;++i)
g[i]=false;
for(scanf("%d",&h);h>-1;scanf("%d",&h))
for(int i=10000;i>=h;--i)
g[i]|=g[i-h];
for(int i=0;i<=10000;++i)
f[i]&=g[i];
}
for(int i=10000;i>=0;--i)
if(f[i]){printf("%d\n",i);break;}
return 0;
} -
09 年前@
#include <iostream>
#include <cstring>using namespace std;
int a[6005];
int b[6005];
int main(){
int n;
cin >> n;
for(int i = 0; i < n; ++i){
int js;
memset(b, 0, sizeof(b));
b[0] = 1;
while(cin >> js){
if(js == -1) break;
for(int i = 6000; i >= 0; --i){
if(b[i] == 1){
b[i + js] = 1;
}
}
}
for(int i = 0; i <= 6000; ++i){
a[i] += b[i];
}
}
for(int i = 6000; i >= 0; --i){
if(a[i] == n){
cout << i << endl;
break;
}
}
} -
010 年前@
#include<cstdio>
#include<memory.h>
const int maxsize=10001;
int n;
bool ac[maxsize]={true},ac2[maxsize]={true},firsttime=true;
int main(){
scanf("%d\n",&n);
memset(ac,true,sizeof(ac));
for(int i=0;i<n;i++){
memset(ac2,false,sizeof(ac2));
ac2[0]=true;
int tmp=0;
while(scanf("%d ",&tmp)!=EOF&&tmp!=-1){
for(int j=maxsize-1;j>=0;j--){
if(ac2[j]){
ac2[j+tmp]=true;
}else;
}
}
for(int j=maxsize-1;j>=0;j--){
ac[j]=ac[j]&&ac2[j];
}
}
for(int i=maxsize-1;i>=0;i--){
if(ac[i]){
printf("%d\n",i);return 0;
}
}
}
01背包水题 -
011 年前@
话说积木不用排序也AC?艹
-
011 年前@
#include <iostream>
#include <climits>
using namespace std;int h[102][102],len[102]={0};
bool F[102][10002]={};int main()
{
int N;
cin >> N;int S_min=INT_MAX;
for(int i=1;i<=N;++i)
{
int S=0;
while(true)
{
cin >> h[i][++len[i]];
if(h[i][len[i]]==-1)
break;
else S+=h[i][len[i]];
}
--len[i];
if(S<S_min)
S_min=S;
}for(int t=1;t<=N;++t)
{
F[t][0]=true;
for(int i=1;i<=len[t];++i)
for(int j=S_min;j>=h[t][i];--j)
if(F[t][j-h[t][i]])
F[t][j]=F[t][j-h[t][i]];
}for(int i=S_min;i>=0;--i)
{
bool OK=true;
for(int t=1;t<=N;++t)
{
OK=OK&&F[t][i];
if(!OK)
break;
}
if(OK)
{
cout << i << endl;
//system("pause");
return 0;
}
}
return 0;
}我好粗心,第一次提交忘了初始化S_min了,第二次提交数组开小了。
-
012 年前@
/*
description: 有n堆积木,每堆由一定数目(<=100)的个积木堆成,每个积木的高度少于100。
现在让你从这n堆积木中抽出一些积木,使得这n堆积木的高度一样,且同时使得高度最大。
solution: 对每一堆积木进行背包,标记每个可以达到的高度,然后找出最大的同时都能达到的高度即可。
author:uncleFun
*/
#include <iostream>
#include <queue>
#include <cstring>
#include <cstdio>
#define MAXN 102
using namespace std ;int n, min_h ;
int b[MAXN][MAXN], ct[MAXN*MAXN], sum[MAXN][MAXN] ;
bool m[MAXN*MAXN] ;
queue<int> que ;void zn_Pack(int k) //01背包
{
int i, j, h, num = b[k][0] ;
memset(m, 0, sizeof(m)) ;
while(!que.empty()) que.pop() ;
que.push(0) ; m[0] = 1 ;
for(i = 1 ; i <= num ; i ++)
{
while(!que.empty())
{
h = que.front() ; que.pop() ;
if(!m[h+b[k][i]]) m[h+b[k][i]] = 1 ;
}
if(i == num) break ;
for(j = 0 ; j <= sum[k][num] ; j ++)
if(m[j]) que.push(j) ;
}
}int solve()
{
int i, j ;
memset(ct, 0, sizeof(ct)) ;
for(i = 1 ; i <= n ; i ++)
{
zn_Pack(i) ;
for(j = 0 ; j <= sum[i][b[i][0]] ; j ++) if(m[j]) ct[j] ++ ;
}
for(i = sum[n][b[n][0]] ; i && (ct[i]!= n) ; i -- ) ;
return i ;
}int main()
{
int i, j, h ;
while (~scanf("%d", &n))
{
while(!que.empty()) que.pop() ;
for(i = 1 ; i <= n ; i ++)
{
j = sum[i][0] = 0 ;
scanf("%d", &h) ;
while (h != -1)
{
b[i][++j] = h ;
sum[i][j] = sum[i][j-1] + h ;
scanf("%d", &h) ;
}
if(j == 0) continue ;
b[i][0] = j ;
}
printf("%d\n", solve()) ;
}
return 0 ;
} -
012 年前@
-
012 年前@
01背包
├ 测试数据 01:答案正确... (0ms, 8308KB)
├ 测试数据 02:答案正确... (0ms, 8308KB)
├ 测试数据 03:答案正确... (0ms, 8308KB)
├ 测试数据 04:答案正确... (0ms, 8308KB)
├ 测试数据 05:答案正确... (0ms, 8308KB)
├ 测试数据 06:答案正确... (0ms, 8308KB)
├ 测试数据 07:答案正确... (0ms, 8308KB)
├ 测试数据 08:答案正确... (0ms, 8308KB)
├ 测试数据 09:答案正确... (0ms, 8308KB)
├ 测试数据 10:答案正确... (12ms, 8308KB)---|---|---|---|---|---|---|---|-
Accepted / 100 / 12ms / 8308KB -
012 年前@
VijosNT Mini 2.0.5.7 Special for Vijos
编译通过...
├ 测试数据 01:答案正确... (0ms, 1596KB)
├ 测试数据 02:答案正确... (0ms, 1596KB)
├ 测试数据 03:答案正确... (0ms, 1596KB)
├ 测试数据 04:答案正确... (0ms, 1596KB)
├ 测试数据 05:答案正确... (0ms, 1596KB)
├ 测试数据 06:答案正确... (0ms, 1596KB)
├ 测试数据 07:答案正确... (0ms, 1596KB)
├ 测试数据 08:答案正确... (0ms, 1596KB)
├ 测试数据 09:答案正确... (0ms, 1596KB)
├ 测试数据 10:答案正确... (0ms, 1596KB)
用递推,每座塔分别处理,暴力就过了。。。 -
012 年前@
o(n^3)也可以秒杀。。。囧。
编译通过...
├ 测试数据 01:答案正确... (0ms, 272KB)
├ 测试数据 02:答案正确... (0ms, 272KB)
├ 测试数据 03:答案正确... (0ms, 272KB)
├ 测试数据 04:答案正确... (0ms, 272KB)
├ 测试数据 05:答案正确... (0ms, 272KB)
├ 测试数据 06:答案正确... (0ms, 272KB)
├ 测试数据 07:答案正确... (0ms, 272KB)
├ 测试数据 08:答案正确... (0ms, 272KB)
├ 测试数据 09:答案正确... (0ms, 272KB)
├ 测试数据 10:答案正确... (0ms, 272KB)---|---|---|---|---|---|---|---|-
Accepted / 100 / 0ms / 272KB