5.6解题报告
来源:互联网 发布:diy在线定制系统 源码 编辑:程序博客网 时间:2024/05/22 16:56
1.Subset Sums 集合
这一道题目,我们可以用到背包问题的方案计数,那么用f[i]表示和为i的方案数,可以推出状态转移方程:f[i]=f[j-i](j=m/2,i),m为所有数的和。
具体看代码:
#include<stdio.h>#include<stdlib.h>#include<string.h>#include<iostream>using namespace std;int n,ans,a[41],mu;long long f[10001];int main() { freopen("sub.in","r",stdin); freopen("sub.out","w",stdout); int i,j,k,m; scanf("%d",&n); for(i=1; i<=n; i++) { a[i]=i; mu+=i; } if(mu%2) { cout<<0<<endl; return 0; } m=mu; f[0]=1; for(i=1; i<=n; i++) for(j=m/2; j>=i; j--) f[j]+=f[j-i]; printf("%lld",f[m/2]/2); return 0;}
2.Longest Prefix 最长前缀
这一题有许多坑,注意标注了**的地方。
思想如下:
我们可以把每一个元素看成背包中的代价(就是重量),那么他的长度就是他的价值,又因为每一个物件可以取无数个,所以就成了一个完全背包。
#include<stdio.h>#include<stdlib.h>#include<string.h>#include<iostream>using namespace std;char s[251][11],kkk[200001];char c[500001],d[11];int n,ans,a[251],f[500001];int pipei(int j,int i){ for(int k=0;k<a[j];k++) if(s[j][k]!=c[i+k])return 0; return 1;}int maxn(int a,int b){ return a>b?a:b;}void dfs(int i){ for(int j=1;j<=n;j++){ if(pipei(j,i)==1 && strlen(s[j])+i<strlen(c)){ ans=maxn(ans,i+strlen(s[j])); dfs(i+strlen(s[j])); } }}void inser(int j,int k){ for(int i=j;i<k;i++) d[i-j]=c[i];}int pd(int j){ for(int i=0;i<a[j];i++) if(d[i]!=s[j][i])return 0; return 1;}int main(){ freopen("prefix.in","r",stdin); freopen("prefix.out","w",stdout); int i,j,k,m; while(!feof(stdin)){ scanf("%s",s[++n]); if(s[n][0]=='.'){ n--;break; } a[n]=strlen(s[n]);// puts(s[n]); } scanf("\n"); while(cin>>kkk){ strcat(c,kkk); } m=strlen(c);// dfs(0); f[0]=1; for(i=1;i<=m;i++) for(j=1;j<=n;j++) if(i>=a[j]) if(f[i-a[j]]){ int ll=0; memset(d,0,sizeof(d)); for(k=i-a[j];k<i;k++) d[ll++]=c[k];// puts(d); if(!strcmp(d,s[j]))f[i]=1; } for(i=strlen(c);i>=0;i--) if(f[i]){ cout<<i<<endl; return 0; } return 0;}
3.Zero Sum 和为零
这一题我本以为要什么高深的算法,竟然搜索+栈处理(中缀求和)就AC了。
#include<stdio.h>#include<stdlib.h>#include<string.h>#include<algorithm>#include<iostream>using namespace std;int a[11],n,d[11],sum,ans,p[11];void out(){ for(int i=1;i<=n;i++){ if(d[i]){ printf("%d",d[i]); if(i==n)break; if(p[i]==1)printf("+"); else if(p[i]==2)printf("-"); else if(p[i]==3)printf(" "); } } puts("");}int calc(){ int kkk=n,rj=0,i; for(i=1;i<=n;i++){ int x=0,k=i; while(p[i]==3){ x=x*10+d[i++]; } if(i<=n)x=x*10+d[i]; a[++rj]=x; }// out(); int come=2; for(i=1;i<=n;i++) if(p[i]!=3){ if(p[i]==1) a[1]=a[1]+a[come++]; else a[1]=a[1]-a[come++]; } return a[1];} void dfs(int i){ for(int j=1;j<=3;j++){ if(j==1)p[i]=3; else if(j==2)p[i]=1; else p[i]=2; if(i<n-1)dfs(i+1); else if(calc()==0){ ans++;out(); } }}int main(){ freopen("sum.in","r",stdin); freopen("sum.out","w",stdout); int i,j,k,m; scanf("%d",&n); for(i=1;i<=n;i++){ d[i]=i; } p[n]=3; dfs(1);// printf("%d\n",ans); return 0;}
4.Money Systems 货币系统
这如同第一题,也是背包问题的方案计数,重点记住要开long long,而且循环的顺序也有坑,不信你可以试试
#include<stdio.h>#include<stdlib.h>#include<string.h>#include<algorithm>#include<iostream>using namespace std;long long ans=0;int n,v;long long f[10001],a[26];int main(){ freopen("money.in","r",stdin); freopen("money.out","w",stdout); int i,j,k; scanf("%d%d",&v,&n); for(i=1;i<=n;i++){ scanf("%lld",&a[i]); } f[0]=1; for(i=1;i<=v;i++) for(j=1;j<=n;j++) if(j>=a[i])f[j]=f[j]+f[j-a[i]]; printf("%lld\n",f[n]); return 0;}
1 0
- 5.6解题报告
- 解题报告
- 解题报告
- 解题报告
- 解题报告
- 解题报告
- 解题报告
- 解题报告
- Antiprime解题报告
- expr解题报告
- 华容道解题报告
- tju解题报告
- zju1062/pku1095解题报告
- UsacoGate解题报告 --- 序曲
- ZJU 2060 解题报告
- ZJU 1331 解题报告
- ZJU 1115 解题报告
- ZJU1057解题报告
- 循环链表实现约瑟夫问题
- 不要62
- Unity常用脚本类继承关系图
- Problem D: 字符类的封装
- UVa 540
- 5.6解题报告
- FPGA固化方法
- 王小草【机器学习】笔记--提升
- react demo7 (设置组件自身属性...this.props)
- JavaScript中的跨域详解(内附源码)
- 2017.5.6 子矩阵 思考记录
- STM32 中JTAG 引脚作为普通IO口设置方法
- vector实现三维数组
- 【BOM】Window对象、事件、方法及DOM与BOM的区别联系