T1:
题目大意:
现在有n个宽度为1的矩形.
我们考虑将其中一些宽度为1的矩形取出,按照原顺序再次紧密地靠在一起.
现在,你的任务就是从原图中取出若干个宽度为1的矩形并使用上面的方式组成新的图形,使得新的图形中,内部的最大矩形面积最大.
输出最大面积.
很水的题,大家都A了,可是Rank1好像这题挂了,只有60分.
我的思路就是因为可以删掉任意的矩形.
所以我们可以判断一下高于或等于某个矩形高度的矩形有多少个,然后乘上这个矩形高度,与最大值取最大当结果.
那么我们只需要把矩形按高度排一下序,暴力枚举就行了.
时间复杂度O(Tnlog(n)),算法复杂度瓶颈在于排序.
考场AC代码如下:
#include<bits/stdc++.h> using namespace std; typedef long long LL; #define ACF inline void const int N=100000; LL h[N+1],ma; int n; ACF into(){ ma=0; scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d",&h[i]); } ACF work(){ sort(h+1,h+n+1); for (int i=1;i<=n;i++) ma=max(ma,LL(n-i+1)*h[i]); } ACF outo(){ printf("%lld\n",ma); } int main(){ //freopen("rectangle.in","r",stdin); //freopen("rectangle.out","w",stdout); int T; scanf("%d",&T); while (T--){ into(); work(); outo(); } return 0; }
T2:
题目大意:
有n个人坐成一排,这n个人都在某一个小组中,同一个小组的所有人所坐的位置一定是连续的.
有一个记者在现场进行采访,他每次采访都会询问一个人其所在的小组有多少人,被询问的每个人都给出了正确的答案,但是由于时间仓促,记者不一定询问了每个人,我们记录一个长度为n的答案序列,序列的第i个数表示第i个人的回答,如果为0则表示记者没有询问过这个人.
记者发现,对于一些情况,他可以唯一确定这排所有人的分组,而对于另外一些情况则不能,于是记者开始好奇,对于某一个答案序列,他能不能做到这一点,如果能的话输出1,否则输出0.
这道题好像比较难,结果就是一个计数DP.
用f[i]表示1~i的方案总数,之后用j表示枚举i所在的组的人数,然后用f[i]=f[i-j]的和.
我们让j从i枚举到1,记录一个x,表示最后一个遇到的有数值(数值不是0)的a[j]的数值.
先实时更新x.
更新的过程中,若x不为0且与当前a[j]不相等,说明已经不是一组的了,直接弹出.
若x为0,说明这里都不确定直接加上f[j-1].
若x不为0,我们就要判断这个x与当前i-j+1是否相等,相等则更新.
其次,当f[i]>2时其实没有什么意义,直接f[i]=2就可以了.
也就是说当已经求得f[i]>=2时,直接f[i]=2后弹出就行了.
AC代码如下:
#include<bits/stdc++.h> using namespace std; #define ACF inline void const int N=1000; int n,T,a[N+1],f[N+1]; ACF start(){ for (int i=0;i<=n;i++) f[i]=0; } ACF into(){ scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d",&a[i]); } ACF work(){ f[0]=1; for (int i=1;i<=n;i++) for (int j=i,x=0;j>=1;j--){ if (a[j]){ if (x&&a[j]&&x!=a[j]) break; if (a[j]) x=a[j]; } if (x==0||i-j+1==x){ f[i]+=f[j-1]; if (f[i]>=2) { f[i]=2; break; } } } } ACF outo(){ if (f[n]==1) printf("1\n"); else printf("0\n"); } int main(){ scanf("%d",&T); while (T--){ start(); into(); work(); outo(); } return 0; }
T3:
题目大意:
给定一个华容道局面,求出曹操是否可以达到最下面的中间两个,若可以,输出最小步数.
华容道就是某著名游戏,不知道的可以点这里.
这道题就是一道很准的bfs,用一个hash就可以稳稳的AC啦.
不过这里把思路理清一下,首先我们用一个矩阵来存状态,跟输入矩阵不同的是,3~7直接用3或4来存,3表示这个大将是横向的,4表示这个大将是纵向的.
然后我们hash的时候就用一个5进制数来表示,记得用long long,然后用一个set来存.
由于2、3、4的情况会使从同一个状态发展出相同的情况,所以我们可以绘制一张表:
const int tx[5][4]={{},{0,0,0,0},{1,1,0,0},{1,1,0,0},{0,0,0,0}}; const int ty[5][4]={{},{0,0,0,0},{1,0,1,0},{0,0,0,0},{1,0,1,0}};
这张表的作用就是判重.
然后随便搞个方位数组就可以了:
const int x_[4]={0,1,0,-1},y_[4]={1,0,-1,0}
那么主要代码如下:
#include<bits/stdc++.h> using namespace std; typedef long long LL; #define ACF inline void const int N=7,M=6; const int x_d[4]={0,1,0,-1},y_d[4]={1,0,-1,0}; const int tx[5][4]={{},{0,0,0,0},{1,1,0,0},{1,1,0,0},{0,0,0,0}}; const int ty[5][4]={{},{0,0,0,0},{1,0,1,0},{0,0,0,0},{1,0,1,0}}; struct node{ int a[N][M]; }s; int n=5,m=4,T,tr[8]; LL hash(node s){ LL sum=0LL; for (int i=n;i>=1;i--) for (int j=m;j>=1;j--) sum=sum*5+tr[s.a[i][j]]; return sum; } ACF into(){ for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) scanf("%d",&s.a[i][j]); } ACF work(){ for(int i=0;i<=n+1;++i) s.a[i][0]=s.a[i][m+1]=-1; for(int j=0;j<=m+1;++j) s.a[0][j]=s.a[n+1][j]=-1; for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) if (s.a[i][j]>=3){ if (s.a[i][j]==s.a[i+1][j]||s.a[i][j]==s.a[i-1][j]) tr[s.a[i][j]]=3; if (s.a[i][j]==s.a[i][j+1]||s.a[i][j]==s.a[i][j-1]) tr[s.a[i][j]]=4; }else tr[s.a[i][j]]=s.a[i][j]; } int bfs(){ queue < node > q; queue < int > qs; set < LL > ss; q.push(s);qs.push(0); ss.insert(hash(s)); if (s.a[n-1][2]==2&&s.a[n-1][3]==2&&s.a[n][2]==2&&s.a[n][3]==2) return 0; while (!q.empty()){ node s=q.front(); q.pop(); int nows=qs.front(); qs.pop(); for (int i=1;i<=n;i++) for (int j=1;j<=m;j++){ int hh=tr[s.a[i][j]],hg=s.a[i][j]; if (!hh) continue; bool flag=1; for(int b=0;b<4;++b) flag=(flag&&s.a[i+tx[hh][b]][j+ty[hh][b]]==s.a[i][j]); if (!flag) continue; for (int e=0;e<4;e++) s.a[i+tx[hh][e]][j+ty[hh][e]]=0; for (int e=0;e<4;e++){ int x=i+x_d[e],y=j+y_d[e]; bool ok=true; for(int b=0;b<4;++b) ok=(ok&&s.a[x+tx[hh][b]][y+ty[hh][b]]==0); if(!ok) continue; for (int g=0;g<4;g++) s.a[x+tx[hh][g]][y+ty[hh][g]]=hg; LL h=hash(s); if (!ss.count(h)){ q.push(s); qs.push(nows+1); ss.insert(h); if (s.a[n-1][2]==2&&s.a[n-1][3]==2&&s.a[n][2]==2&&s.a[n][3]==2) return nows+1; } for (int g=0;g<4;g++) s.a[x+tx[hh][g]][y+ty[hh][g]]=0; } for (int e=0;e<4;e++) s.a[i+tx[hh][e]][j+ty[hh][e]]=hg; } } return -1; } ACF outo(){ printf("%d\n",bfs()); } int main(){ scanf("%d",&T); while (T--){ into(); work(); outo(); } }
把y=j+y_d[e]打成y=j+x_d[e]...手残...
万恶的老刘尽然让我写如此丧心病狂之码农题...
害的我的线段树都没写...