10月集训test10
来源:互联网 发布:linux cp 带目录结构 编辑:程序博客网 时间:2024/05/31 18:31
又是写考试总结的时候了。。。。
这次考试60+10+55=125.
第一题真心是没有找到更优的方法,后面丢的分全是因为超时;第二题并没有想到动规,所以华丽丽拿了特判的分;第三题。。大概是暴力写炸了吧(不过其实暴力就可以直接过正解了)。
天凉了,让死去的脑细胞埋得更深一点吧。
1.刮刮卡
问题描述
企鹅豆豆在和一个良心商贩玩刮刮卡。
一张刮刮卡价值为A元,刮开可以获得B元现金和B个积分。由于商贩特别良心,所以他告诉了豆豆每张刮刮卡的A和B值,并且允许豆豆先拿到B元现金再支付A元费用。他同时保证,所有刮刮卡得到的钱等于购买所有刮刮卡花费的钱。现在他把刮刮卡排成一列,放在豆豆面前。
地主家的傻儿子豆豆有顺着买的强迫症,所以他会先把序列最前面K张刮刮卡顺次移到最后面,然后开始顺着一张一张得和商贩交易。豆豆一开始不亏不赚,如果某个时刻某张卡片交易结束之后,他有亏损的话就会结束这个交易。
豆豆并不在意自己能赚多少,反而他对积分很感兴趣。他想知道K取多少他才能尽可能多地得到积分。
输入格式
第一行一个整数N代表总刮刮卡个数。
接下来一行N个数,表示第i张刮刮卡的Bi值。
接下来一行N个数,表示第i张刮刮卡的Ai值。
输出格式
输出一个整数K,如果得到的积分相同,输出最小的K。
输入样例
5
4 6 2 8 4
1 5 7 9 2
输出样例
4
样例说明
如果一张都不挪动(K=0),豆豆最终会得到12积分。
如果把前四张放到最后(4 4 6 2 8),豆豆最终可以得到24积分。
数据范围
对于30%的数据,N≤1000。
对于100%的数据,N≤1000000,0≤Ai,Bi≤1000。
不得不说,被加粗了的那句话是很重要的一句,这标志着总有一种排列使得最终的积分为Ai或是Bi的和。这是先以任意卡片为起点,算出所有卡片的前缀和,则前缀和最小的卡片应为起始卡片,再算出若以它为起点该移动多少张牌即可。
#include<iostream>#include<cstdlib>#include<cstdio>#include<cstring>#include<string>#include<ctime>#include<cmath>#include<algorithm>#include<cctype>#include<iomanip>using namespace std;int n,x;bool f[1000010];int a[1000010],b[1000010];inline int read(){ int i=0; char c; for(c=getchar();c<'0'||c>'9';c=getchar()); for(;c>='0'&&c<='9';c=getchar()) i=(i<<1)+(i<<3)+c-'0'; return i;}int main(){ //freopen("rock.in","r",stdin); //freopen("rock.out","w",stdout); n=read(); for(int i=1;i<=n;i++) b[i]=read(); for(int i=1;i<=n;i++) { x=read(); a[i]=b[i]-x; } for(int i=1;i<=n;i++) a[i]+=a[i-1]; int mn=1e9,pos=-1; for(int i=0;i<n;i++) if(a[i]<mn) mn=a[i],pos=i; cout<<pos<<endl; return 0;}
2.矩阵
问题描述
豆豆在玩一个N行M咧的矩阵,他现在需要从中选出恰好K个不互相重叠的非空子矩阵。他的得分为这些子矩阵的数值之和。他想知道他最多能得多少分?
输入格式
第一行为N,M,K表示矩阵的行数和列数以及K值。
接下来K行,每行M个数字描述矩阵每行中的每个元素的数值。
输出格式
输出一个整数表示最多的得分。
输入样例
3 2 2
1 -3
2 3
-2 3
输出样例
9
数据范围
对于20%的数据,M≤1,K≤1;
对于50%的数据,M≤1,K≤10;
对于另外10%的数据,0≤数值;
对于100%的数据,1≤N≤100,1≤M≤2,1≤K≤10,|数值|≤1000000。
用动态规划,分两种情况讨论。
一种是m=1,开一个二维数组f[i][j],表示当前处理了i个数,已经用了j个矩阵时能够获得的最大值
状态转移方程:f[i][j]=max(f[i][j],f[j][i-1]+a[i]-a[j])
还有一种m=2,开一个三维数组f[i][j][k]表示扫描到第一列i位置与第二列j位置且选取k个矩阵的答案。
转移有三种:第一列取一段,第二列取一段,取一个宽度为2的矩阵。
#include<iostream>#include<cstdlib>#include<cstdio>#include<cstring>#include<string>#include<ctime>#include<cmath>#include<algorithm>#include<cctype>#include<iomanip>using namespace std;int n,m,k,ans;int a[110][4],f1[110][110],f2[110][110][110];inline int read(){ int i=0,f=1; char c; for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar()); if(c=='-') f=-1,c=getchar(); for(;c>='0'&&c<='9';c=getchar()) i=(i<<1)+(i<<3)+c-'0'; return i*f;}inline void zql(){ memset(f1,-10,sizeof(f1)); for(int i=0;i<=n;i++) f1[i][0]=0; for(int i=1;i<=n;i++) for(int j=1;j<=k;j++) { f1[i][j]=f1[i-1][j]; for(int t=0;t<=i-1;t++) f1[i][j]=max(f1[i][j],f1[t][j-1]+a[i][1]-a[t][1]); } ans=f1[n][k];}inline void zzk(){ memset(f2,-10,sizeof(f2)); for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) f2[i][j][0]=0; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) for(int t=1;t<=k;t++) { f2[i][j][t]=max(f2[i-1][j][t],f2[i][j-1][t]);//第一行。 for(int p=0;p<=i-1;p++) f2[i][j][t]=max(f2[i][j][t],f2[p][j][t-1]+a[i][1]-a[p][1]);//第二行。 for(int p=0;p<=j-1;p++) f2[i][j][t]=max(f2[i][j][t],f2[i][p][t-1]+a[j][2]-a[p][2]); if(i==j) for(int p=0;p<=i-1;p++) f2[i][j][t]=max(f2[i][j][t],f2[p][p][t-1]+a[i][1]-a[p][1]+a[i][2]-a[p][2]); }//取一个宽度为2的矩阵。 ans=f2[n][n][k];}int main(){ //freopen("matrix.in","r",stdin); //freopen("matrix.out","w",stdout); n=read(),m=read(),k=read(); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) a[i][j]=read(),a[i][j]+=a[i-1][j]; if(m==1) zql(); if(m==2) zzk(); cout<<ans<<endl; return 0;}
3.裁剪表格
问题描述
豆豆有一个n行m列的表格,每个格子里都有一个数字v。
豆豆学完了高级数据结构后,想拿这个表格练手。
所以他想出了这么一个问题:
每次在表格中取出不相邻(不相邻是指不相交且没有共同的边界,但是可以有一样的顶点)的两个大小一样的子矩阵,然后交换这两个子矩阵。这样操作q次之后,这个原有表格会变成什么样子?
输入格式
第一行三个整数n,m,q代表表格的行数和列数以及操作次数。
接下来n行,每行m个整数,表示表格中的数字。
接下来q行,每行六个整数r1,c1,r2,c2,h,w分别表示第一个矩形左上角所在行、所在列,第二个矩形左上角所在行、所在列,这两个矩形的高度和宽度(保证这两个矩形都在原有表格内)。
输出格式
输出n行,每行m个整数,表示最终表格中的数字,用空格隔开。
输入样例
4 4 2
1 1 2 2
1 1 2 2
3 3 4 4
3 3 4 4
1 1 3 3 2 2
3 1 1 3 2 2
输出样例
4 4 3 3
4 4 3 3
2 2 1 1
2 2 1 1
数据范围
对于10%的数据,所有的v=1;
对于30%的数据,n,m≤300,q≤300;
对于60%的数据,n,m≤1000,q≤500;
对于100%的数据,2≤n,m≤1000,1≤q≤10000,1≤v≤1000000。
这道题真的不想多说,暴力直接过,100分。
#include<iostream>#include<cstdlib>#include<cstdio>#include<cstring>#include<string>#include<ctime>#include<cmath>#include<algorithm>#include<cctype>#include<iomanip>using namespace std;int n,m,q,r1,c1,r2,c2,h,w;int s[3300][3300];inline int read(){ register int i=0,f=1; char ch=getchar(); for(ch;ch>'9'||ch<'0'&&ch!='-';ch=getchar()); if(ch=='-') ch=getchar(),f=-1; for(ch;ch>='0'&&ch<='9';ch=getchar()) i=(i<<1)+(i<<3)+ch-'0'; return i*f;}int main(){ n=read(),m=read(),q=read(); for(register int i=1;i<=n;i++) for(register int j=1;j<=m;j++) s[i][j]=read(); while(q--) { r1=read(),c1=read(),r2=read(),c2=read(),h=read(),w=read(); for(register int i=0;i<h;i++) for(register int j=0;j<w;j++) swap(s[r1+i][c1+j],s[r2+i][c2+j]); } for(register int i=1;i<=n;i++) { for(register int j=1;j<=m;j++) cout<<s[i][j]<<" "; cout<<endl; } return 0;}
以上。
来自2017.10.20.
——我认为return 0,是一个时代的终结。
- 10月集训test10
- 暑假集训test10
- test10
- test10
- test10
- 10月集训test3
- 10月集训test4
- 10月集训test5
- 10月集训test6
- 10月集训test7
- 10月集训test8
- 10月集训test9
- 10月集训test11
- 10月集训test12
- 10月集训test13
- 10月集训test14
- 10月集训test15
- 10月集训test16
- 字符串的排列——28
- 关于HTTP中的keep-alive
- 数据库之——索引、触发器、事务(存储引擎)
- 漫谈shell脚本
- jsp中div 标签到底有什么用?
- 10月集训test10
- bzoj 3171: [Tjoi2013]循环格 费用流
- 【洛谷】2831 [Noip2016]愤怒的小鸟 状压DP
- mysql语句执行时间分析
- 【论文阅读】Shakti-T: A RISC-V Processor with Light Weight Security Extensions
- js获取url传递参数
- C#方法递归
- 括号匹配的检验
- 利用AD13设计PCB的问题总结21-30