您的位置:首页 > 其它

奋斗群群赛18总结与心得

2017-10-09 13:03 253 查看
总体情况

T1
思路

T2
思路

T3
思路

T4
思路

T5
思路

总体情况

这次并不是CF上的题,不知道老师昨天经历了什么给我们放了什么鬼题.前4题都是背包,最后一题是树形DP.

T1

http://poj.org/problem?id=1837

思路

01背包.

#include<cstdio>
using namespace std;
int a[50],b[50],dp[50][10000];
int main()
{
int n,g,i,j,k;
scanf("%d%d",&n,&g);dp[0][7500]=1;
for (i=1;i<=n;i++) scanf("%d",&a[i]);
for (i=1;i<=g;i++) scanf("%d",&b[i]);
for (i=1;i<=g;i++) for (j=0;j<=9999;j++) if (dp[i-1][j]) for (k=1;k<=n;k++) dp[i][j+a[k]*b[i]]+=dp[i-1][j];//枚举所有物品以及总力矩的情况,如果存在上一种,则用每个钩子把总力矩更新一遍
printf("%d",dp[g][7500]);
}


T2

http://poj.org/problem?id=1948

思路

利用背包枚举所有能取到的边长,用海伦公式算出面积的最大值.由于最大边的边长不超过总和的一半,可以从一半开始枚举.

#include<stdio.h>
#include<string
4000
.h>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
int d[50],dp[1000][1000],sum;
int helen(int a,int b,int c){double p=(a+b+c)*1.0/2;return sqrt(p*(p-a)*(p-b)*(p-c))*100;}
int main()
{
int n,i,j,k,ban,answer;
scanf("%d",&n);
for (dp[0][0]=1,i=1;i<=n;i++) scanf("%d",&d[i]),sum+=d[i];
for (ban=sum/2,i=1;i<=n;i++) for (j=ban;j>=0;j--) for (k=j;k>=0;k--) if (j>=d[i]&&dp[j-d[i]][k]||dp[j][k-d[i]]&&k>=d[i]) dp[j][k]=1;
for (answer=-1,i=ban;i>=1;i--) for (j=i;j>=1;j--) if (dp[i][j])
{
k=sum-i-j;
if (i+j>k&&i+k>j&&j+k>i) answer=max(answer,helen(i,j,k));
}
printf("%d",answer);
}


T3

http://acm.split.hdu.edu.cn/showproblem.php?pid=1712

思路

分组背包,也就是对每一组都做一次01背包.

#include<stdio.h>
#include<algorithm>
#include<cstring>
using namespace std;
int main()
{
for (int n,m,i,j,k,a[110][110],dp[110];scanf("%d%d",&n,&m)&&n&&m;printf("%d\n",dp[m]))
{
for (memset(dp,0,sizeof(dp)),i=1;i<=n;i++) for (j=1;j<=m;j++) scanf("%d",&a[i][j]);
for (i=1;i<=n;i++) for (j=m;j>=1;j--) for (k=1;k<=j;k++) dp[j]=max(dp[j],dp[j-k]+a[i][k]);
}
}


T4

http://poj.org/problem?id=3260

思路

付钱是多重背包,找钱是完全背包.我在3小时29分29秒提交了一次,T了.后来我发现我把一个-号打成了=,居然能过样例!注意多重背包要用优化否则时间会炸掉.

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int index=1<<20;
int a[105],b[106],dp1[20560],dp2[20236],n,m,answer;
void duochong(int i)
{
int j,k;
if (a[i]*b[i]>=m+10000) {for (j=a[i];j<=10000+m;j++) dp2[j]=min(dp2[j],dp2[j-a[i]]+1);return;}
for (k=1;k<b[i];b[i]-=k,k*=2) for (j=10000+m;j>=a[i];j--) dp2[j]=min(dp2[j],dp2[j-k*a[i]]+k);//用for循环比起while来精简很多,快速幂也可以这么做
for (j=10000+m;j>=a[i];j--) dp2[j]=min(dp2[j],dp2[j-b[i]*a[i]]+b[i]);
}
int main()
{
scanf("%d%d",&n,&m);
int i,j;
for (i=1;i<=n;i++) scanf("%d",&a[i]);
for (i=1;i<=n;i++) scanf("%d",&b[i]);
memset(dp1,0x3f,sizeof(dp1)),memset(dp2,0x3f,sizeof(dp2));
dp1[0]=0,dp2[0]=0;
for (i=1;i<=n;i++)
{
for (j=a[i];j<=10000+m;j++) dp1[j]=min(dp1[j],dp1[j-a[i]]+1);
duochong(i);
}
for (answer=index,i=m;i<=m+10000;i++) answer=min(dp2[i]+dp1[i-m],answer);
printf("%d",answer==index?-1:answer);
}


T5

http://poj.org/problem?id=2486

思路

大佬做的题目放弃了.

#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
vector<int> g[1010];
int dp[2][1010][210],n,v,val[1010];bool used[1010];
void max(int &a,int b){if (a<b) a=b;}
void dfs(int s)
{
int i;
used[s]=true;
for (i=0;i<=v;i++) dp[0][s][i]=dp[1][s][i]=val[s];
for (i=0;i<g[s].size();i++)
{
int t=g[s][i];
if (used[t]) continue;
dfs(t);
for (int j=v;j>=0;j--) for (int k=0;k<=j;k++)
{
max(dp[0][s][j+2],dp[0][t][k]+dp[0][s][j-k]);
max(dp[1][s][j+2],dp[0][t][k]+dp[1][s][j-k]);
max(dp[1][s][j+1],dp[1][t][k]+dp[0][s][j-k]);
}
}
}
int main()
{
for (int i,a,b;scanf("%d%d",&n,&v)!=EOF;memset(dp,0,sizeof(dp)),memset(used,false,sizeof(used)),dfs(1),printf("%d\n",dp[1][1][v]))
{
for (i=0;i<=1000;i++) g[i].clear();
for (i=1;i<=n;i++) scanf("%d",&val[i]);
for (i=1;i<n;i++) scanf("%d%d",&a,&b),g[a].push_back(b),g[b].push_back(a);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: