NOIP2017赛前模拟:总结
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NOIP2017赛前模拟:总结相关的知识,希望对你有一定的参考价值。
题目:
1.刮刮卡
已知n(n<=1000000)张刮刮卡按顺序排列,刮开可以获得B元现金和B个积分,购买刮刮卡需要A元,某人若按照顺序刮开的话··当B的总和小于A时便会停止刮卡(即花出去的钱多余赢得的钱),现在我们可以将前k张按原来的顺序放到后面去···问k取多少时这个人可以获得多少积分?
2.矩阵
给出一个n行m阵的矩阵(n,m<=100),问如果从中选出K个互不重叠的非空子矩阵使得子矩阵的和最大
3.裁剪表格
给出n行m列的矩阵··(n,m<=1000)和q(q<=10000)次操作··每次操作交换两个互不重合的子矩阵···输出最后的矩阵
题解:
1.最大子串和
略
代码:
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<ctime> #include<cctype> #include<string> #include<cstring> #include<algorithm> using namespace std; const int N=2e6+5; inline int R() { char c;int f=0; for(c=getchar();c<‘0‘||c>‘9‘;c=getchar()); for(;c<=‘9‘&&c>=‘0‘;c=getchar()) f=(f<<3)+(f<<1)+c-‘0‘; return f; } int num[N*2],a[N],b[N*2],n; int main() { //freopen("rock.in","r",stdin); //freopen("rock.out","w",stdout); n=R();int ans=0,sum1=0,maxx=0,sum2=0; for(int i=1;i<=n;i++) b[i]=b[i+n]=R(); for(int i=1;i<=n;i++) a[i]=R(),num[i]=num[i+n]=b[i]-a[i]; int Head=1; while(Head<=n) { if(num[Head]<0) {Head++;continue;} int Tail=Head;sum1=0,sum2=0; while(Tail-Head+1<=n) { sum1+=num[Tail]; sum2+=b[Tail]; if(sum2>maxx) maxx=sum2,ans=Head-1; if(Tail-Head+2<=n&&sum1+num[Tail+1]>=0) Tail++; else break; } Head=Tail+1; } cout<<ans<<endl; return 0; }
2.dp
用f[i][j][k]表示第一列取了前i个,第二列取了前j个且组成了k个子矩阵的最小值,具体转移方程看代码吧··
md考试时忘记初始化-inf了····下次一定要注意··
代码:
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<ctime> #include<cctype> #include<string> #include<cstring> #include<algorithm> using namespace std; const int N=105; const int K=15; const long long inf=1e+18; int n,m,k,num[N],map[N][5]; long long f1[N],sum[5][N],temp[N],f2[N][N][K]; inline int R() { char c;int f=0,i=1; for(c=getchar();(c<‘0‘||c>‘9‘)&&c!=‘-‘;c=getchar()); if(c==‘-‘) i=-1,c=getchar(); for(;c<=‘9‘&&c>=‘0‘;c=getchar()) f=(f<<3)+(f<<1)+c-‘0‘; return f*i; } int main() { //freopen("matrix.in","r",stdin); // freopen("matrix.out","w",stdout); n=R(),m=R(),k=R(); if(m==1) { for(int i=1;i<=n;i++) num[i]=R(); memset(f1,-10,sizeof(f1)); f1[0]=0; for(int i=1;i<=k;i++) { for(int j=i;j<=n;j++) { if(j==i) f1[j]=temp[j-1]+num[j]; else f1[j]=max(f1[j-1]+num[j],temp[j-1]+num[j]); } for(int j=i;j<=n;j++) { if(j==i) temp[j]=f1[j]; else temp[j]=max(temp[j-1],f1[j]); } } long long ans=-inf; for(int i=k;i<=n;i++) ans=max(ans,f1[i]); cout<<ans<<endl; } else { memset(f2,-10,sizeof(f2)); long long tot=0;bool flag=true; for(int i=1;i<=n;i++) for(int j=1;j<=2;j++) { map[i][j]=R();tot+=map[i][j]; if(map[i][j]<0) flag=false; sum[j][i]=sum[j][i-1]+map[i][j]; } if(flag) { cout<<tot<<endl;return 0; } for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) f2[i][j][0]=0; for(int i=1;i<=k;i++) for(int j=1;j<=n;j++) //第一列 for(int l=1;l<=n;l++) //第二列 { f2[j][l][i]=max(f2[j-1][l][i],f2[j][l-1][i]); for(int p=0;p<j;p++) f2[j][l][i]=max(f2[j][l][i],f2[p][l][i-1]+sum[1][j]-sum[1][p]); for(int p=0;p<l;p++) f2[j][l][i]=max(f2[j][l][i],f2[j][p][i-1]+sum[2][l]-sum[2][p]); if(l==j) for(int p=0;p<j;p++) f2[j][l][i]=max(f2[j][l][i],f2[p][p][i-1]+sum[2][l]-sum[2][p]+sum[1][j]-sum[1][p]); } cout<<f2[n][n][k]<<endl; } return 0; }
3.链表
看了题解后发现链表是一个神奇的东西··另外也发现register配上for循环的优化效果的显著···
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<ctime> #include<cctype> #include<cstring> #include<string> #include<algorithm> using namespace std; const int N=1005; int n,m,q,pos[N][N],ri[N*N],down[N*N],val[N*N],tot; inline int R() { char c;int f=0; for(c=getchar();c<‘0‘||c>‘9‘;c=getchar()); for(;c<=‘9‘&&c>=‘0‘;c=getchar()) f=(f<<3)+(f<<1)+c-‘0‘; return f; } inline int find(int x,int y) { int t=pos[0][0]; for(int i=1;i<=x;i++) t=down[t]; for(int i=1;i<=y;i++) t=ri[t]; return t; } int main() { //freopen("a.in","r",stdin); n=R(),m=R(),q=R(); for(register int i=1;i<=n;i++) for(register int j=1;j<=m;j++) val[pos[i][j]=++tot]=R(); for(register int i=0;i<=m+1;i++) pos[0][i]=++tot,pos[n+1][i]=++tot; for(register int i=1;i<=n;i++) pos[i][0]=++tot,pos[i][m+1]=tot; for(register int i=0;i<=n;i++) for(register int j=0;j<=m;j++) { ri[pos[i][j]]=pos[i][j+1]; down[pos[i][j]]=pos[i+1][j]; } while(q--) { int r1=R(),c1=R(),r2=R(),c2=R(),h=R(),w=R(); register int t1=find(r1-1,c1-1),t2=find(r2-1,c2-1),T1,T2,i; for(T1=t1,T2=t2,i=1;i<=h;i++) swap(ri[T1=down[T1]],ri[T2=down[T2]]); for(i=1;i<=w;i++) swap(down[T1=ri[T1]],down[T2=ri[T2]]); for(T1=t1,T2=t2,i=1;i<=w;i++) swap(down[T1=ri[T1]],down[T2=ri[T2]]); for(i=1;i<=h;i++) swap(ri[T1=down[T1]],ri[T2=down[T2]]); } int p=pos[0][0]; for(register int i=1;i<=n;i++) { p=down[p]; for(register int j=1,t=p;j<=m;j++) cout<<val[t=ri[t]]<<" "; cout<<endl; } return 0; }
以上是关于NOIP2017赛前模拟:总结的主要内容,如果未能解决你的问题,请参考以下文章