2018年全国多校算法寒假训练营练习比赛(第二场)B C F G(E待补)
emmmmmm非常非常基础的01背包,分两种情况,h为0和不为0。。。背包的东西可以看看背包9讲,讲的很详细,直接找度娘就能找到。
#include<iostream> #include<string.h> #include<algorithm> using namespace std; int w[105],v[105]; int dp[205]; int n,h,m; int main() { while(cin>>n&&n) { cin>>m>>h; for(int i=0;i<n;i++) cin>>w[i]>>v[i]; memset(dp,0,sizeof(dp)); int ans=0; if(!h) { for(int i=0;i<n;i++) for(int j=m;j>=w[i];j--) dp[j]=max(dp[j-w[i]]+v[i],dp[j]); ans=max(ans,dp[m]); } else{ for(int k=0;k<n;k++) { memset(dp,0,sizeof(dp));//不要忘了初始化啊 !!!orz for(int i=0;i<n;i++) { if(i==k) continue; for(int j=m+h-1;j>=w[i];j--) dp[j]=max(dp[j-w[i]]+v[i],dp[j]); } ans=max(ans,dp[m+h-1]+v[k]); } } cout<<ans<<endl; } }
C 小仙女过生日
区间DP 三角剖分()
#include<bits/stdc++.h> using namespace std; const int maxn=105; int n; struct point { double x,y; }p[maxn]; double dp[maxn][maxn]; double S(point a,point b,point c) { return fabs((a.x-c.x)*(b.y-c.y)-(b.x-c.x)*(a.y-c.y))/2.0; //叉乘计算三角形面积(高中学的都忘了QAQ) } bool C(int a,int b,int c) //以p[a],p[b],p[c]为所切割三角形的顶点,如果存在第4个点在这三个点内部,则切割方案不可行,切割必然会出现交点
{ double m=S(p[a],p[b],p[c]); for(int i=1;i<=n;i++) { if(i==a||i==b||i==c) continue; double temp=S(p[a],p[b],p[i])+S(p[a],p[c],p[i])+S(p[b],p[c],p[i])-m;//这里用面积来判断 if(fabs(temp)<=1e-8 )return 0; } return 1; } int main() { while(cin>>n) { for(int i=1;i<=n;i++) cin>>p[i].x>>p[i].y; for(int d=3;d<=n;d++) { for(int i=1;i+d-1<=n;i++) { if(d==3) {dp[i][i+2]=S(p[i],p[i+1],p[i+2]);continue;} //每次循环前先对dp数组初始化
int j=i+d-1; dp[i][j]=0x3f3f3f3f; for(int k=i+1;k<j;k++) { if(C(i,k,j)) dp[i][j]=min(dp[i][j],max(max(S(p[i],p[j],p[k]),dp[i][k]),dp[k][j])); } } } printf("%.1f\n",dp[1][n]); } return 0; }
F 德玛西亚万岁
依旧基础的状压DP,跟poj3254是一个题=-=,数据一点都没改,直接拿那个题的代码交……直接A
//状压DP真的要好好的注意一下()的问题,=-=总感觉这个运算优先级很微妙
#include<iostream> #include<string.h> #include<algorithm> #include<cmath> using namespace std; typedef long long ll; const int maxn=15; const int maxm=15; const int mod=100000000; int n,m; int mz[maxn][maxm]; int dp[maxn][1<<maxm],v[1<<maxm]; void init() { int cnt=0; for(int i=0;i<(1<<maxm);i++) if(!(i&(i<<1))) v[cnt++]=i; } int C(int x,int y) { for(int i=0;i<m;i++) if((y&(1<<i))&&!mz[x][i]) return 1; return 0; } void DP() { for(int i=0;i<n;i++) for(int s=0;v[s]<(1<<m);s++) { if(C(i,v[s])) continue; if(i==0) { dp[i][s]=1; continue; } for(int j=0;v[j]<(1<<m);j++) { if((v[s]&v[j])==0) dp[i][s]+=dp[i-1][j]; } } } int main() { init(); while(cin>>n>>m) { memset(dp,0,sizeof(dp)); for(int i=0;i<n;i++) for(int j=0;j<m;j++) cin>>mz[i][j]; int ans=0; DP(); for(int i=0;v[i]<(1<<m);i++) ans=(ans+dp[n-1][i])%mod; cout<<ans<<endl; } return 0; }
G 灰常典型的数位dp
emmmm太懒了直接套了以前的板子=-=稍微改了一下,凑合着看吧
#include<bits/stdc++.h> #define lowbit(x) (x&-x) using namespace std; const int maxn=1e5+5; typedef long long LL; int n; int bit[100]; LL dp[100][100]; LL DP(int p,int m,int flag) { if(p==0) return (m!=4); if(dp[p][m]!=-1&&flag) return dp[p][m]; int k=flag?9:bit[p]; LL sum=0; for(int i=0;i<=k;i++) { if(i==4) continue; if(m==3&&i!=8) sum+=DP(p-1,i,flag||i!=k); else if(m!=3) sum+=DP(p-1,i,flag||i!=k); } if(flag) dp[p][m]=sum; return sum; } LL solve(LL n) { memset(dp,-1,sizeof(dp)); int num=0; if(n<0) return 0; while(n) { bit[++num]=n%10; n/=10; } return DP(num,0,0); } int main() { int t; LL n,m; while(~scanf("%lld%lld",&n,&m),n+m) { printf("%lld\n",m-n+1-solve(m)+solve(n-1)); } return 0; }