当前位置:
文档之家› NOIP2014普与组复赛试题讲解(c++版本)
NOIP2014普与组复赛试题讲解(c++版本)
➢
d--;r--;
➢
}
➢
}
➢
}
-9-
第4题 “子矩阵”简述
- 10 -
暴力搜索(预计得分50分)
➢ 构造出行(DFS) ➢ 构造出列(DFS) ➢ 计算目前的子矩阵的分值
- 11 -
暴力搜索程序模块
➢ void w(int k)
➢{
if(k==row+1)
➢ { h(1);//进入列搜索
➢
return; }
➢
if(ansa*b1>ansb*a1)
{
➢
else return gcd(y,t);
➢
ansa=a1;
➢}
➢ ansb=b1;
➢ int main()
➢}
➢{
➢
}
➢
int a,b,l,a1,b1,ansa,ansb; ➢ cout<<ansa<<" "<<ansb;
➢
cin>>a>>b>>l;
➢ return 0;
➢
return; }
➢ if(m-c[g-1]>=col-g+1)
➢ { for(int i=c[g-1]+1;i<=m;i++)
➢
{ c[g]=i;
➢
h(g+1);}
➢}
➢}
- 13 -
暴力搜索程序模块
➢ int pd()
➢{
➢ int sum=0;
➢ for(int i=1;i<=row;i++)
➢
for(int j=1;j<=m;j++)
➢
f[1][j]=w[j];
➢
for(int j=2;j<=m;j++)
➢
for(int k=1;k<j;k++)
➢
for(int i=1;i<=m;i++)
➢
v[k][j]+=vx[r[i]][k][j];
➢ for(int i=2;i<=col;i++)
➢ 不过,如果把调查结果就以这种方式呈现出来,大多数人 肯定不会满意。因为这个比例的数值太大,难以一眼看出 它们的关系。对于上面这个例子,如果把比例记为5:3,虽 然与真实结果有一定的误差,但依然能够较为准确地反映 调查结果,同时也显得比较直观。
➢ 现给出支持人数A,反对人数B,以及一个上限L,请你将A 比B化简为A’比B’,要求在A’和B’均不大于L且A’和B’互质 (两个整数的最大公约数是1)的 前 ᨀ 下 ,A’/B’ ≥ A/B且 A’/B’ - A/B的值尽可能小。
➢}
- 15 -
确定解题思路AC
➢ 思路:搜索+DP ➢ 枚举出选那些行 ➢ 算出j列各行之间的分数w[j],k,j两列之间的分数v[k][j]。 ➢ f[i][j]表示已经选了i(数量)列,最后一列是j (下标)的最小分数 且第i列是j ➢ 状态转移方程:f[i][j]=min(f[i-1][k]+w[j]+v[k][j])。
➢ using namespace std;
➢ int gcd(int x,int y)
➢{
➢
int t;
➢
t=x%y;
➢
if(t==0)
➢
return y;
➢
for(a1=l;a1>=1;a1--)
➢
for(b1=l;b1>=1;b1--)
➢
{
➢
if(a1*b>=a1)==1)
- 17 -
参考程序(DP部分)
➢ void dp()
➢{
➢
memset(w,0,sizeof(w));
➢
memset(v,0,sizeof(v));
➢
memset(f,127,sizeof(f));
➢
for(int j=1;j<=m;j++)
➢
for(int i=2;i<=row;i++)
➢
w[j]+=abs(a[r[i]][j]-a[r[i-1]][j]);
- 16 -
数据结构
➢ a[maxn][maxn] // 存放原数据n行m列的矩阵 ➢ r[maxn] // c存放枚举出的行号 ➢ vx[maxn][maxn][maxn] // vx[I][K][J] 记录i行k列与j
列之间的差值的绝对值 ➢ w[maxn]// j列各行之间的分数 ➢ v[maxn][maxn]// k,j两列之间的分数 ➢ f[maxn][maxn]//i列,最后一列是j 的最小分数 且第i列是j
➢ return sum;
➢}
- 14 -
暴力搜索程序模块
➢ int main()
➢{
➢ cin>>n>>m>>row>>col;
➢ for(int i=1;i<=n;i++)
➢ for(int j=1;j<=m;j++)
➢
cin>>a[i][j];
➢ w(1);
➢ cout<<ans;
➢ return 0;
➢ 直接三重循环穷举 ➢ 外层循环枚举和,两个内层循环分别枚举两个加数,如果
有两个数之和对应外层循环的枚举值,退出两个内层循环 ➢ 注意:找到满足等式的必须退出两个内循环。 ➢ 注意看清题意:其中有多少个数,恰好等于集合中另外两
个(不同的)数之和。
-2-
参考程序 C++
➢ #include <iostream>
-4-
确定解题思路
➢ L很小,还是枚举
➢ 分别枚举化简之后的A’和B’ ➢判断A’/B’ >=A/B,避免精度问题,转换成乘法
A’*B>=A*B’
➢ 判断互质,最大公约数为1
➢ 判断A’和B’最小
A’*ansB<=ansA*B’ 找到更小的A’和B’
设置为ansA和ansB
-5-
主程序
➢ #include <iostream>
➢
➢ using namespace std;
➢
➢ int main()
➢
➢{
➢
➢
int n,i,j,k,ans=0;
➢
➢
int a[105];
➢
➢
cin>>n;
➢
➢
for(i=1;i<=n;i++)
➢
➢
cin>>a[i];
➢
➢
for(i=1;i<=n;i++)//和为A[i] ➢
➢
{
➢
➢
bool f=false;
试题分析
BYE
温馨提示: 本题解内的程序都已经AC,由 于代码较长,可以查看CPP文件
The END
2017. 07. 28
知识回顾 Knowledge Review
祝您成功!
➢ if(n-r[k-1]>=row-k+1)
➢ { for(int i=r[k-1]+1;i<=n;i++)
➢
{ r[k]=i;
➢
w(k+1);}
➢}
➢}
- 12 -
暴力搜索程序模块
➢ void h(int g)
➢ { if(g==col+1)
➢ { int t=pd();
➢
if(t<ans) ans=t;
➢ for(int j=i;j<=m;j++)
➢
for(int k=i-1;k<=j-1;k++)
➢
f[i][j]=min(f[i][j],f[i-1][k]+v[k][j]+w[j]);
➢ for(int i=col;i<=m;i++)
➢ ans=min(ans,f[col][i]);
➢}
- 18 -
➢ for(int j=1;j<col;j++)
➢
sum+=abs(a[r[i]][c[j]]-a[r[i]][c[j+1]]);
➢ for(int j=1;j<=col;j++)
➢ for(int i=1;i<row;i++)
➢
sum+=abs(a[r[i]][c[j]]-a[r[i+1]][c[j]]);
➢}
➢
for(j=1;j<n;j++)
➢
{
➢
for(k=j+1;k<=n;k++)
➢
if (a[i]==a[j]+a[k]) {
f=true; ans++; break; } if(f) break; } } cout<<ans; return 0;
-3-
第2题 “比例简化”简述
➢ 在社交媒体上,经常会看到针对某一个观点同意与否的民 意调查以及结果。例如,对某一观点表示支持的有1498 人, 反对的有902 人,那么赞同与反对的比例可以简单的记为 1498:902。
➢
else