A. Marks . 简单题
B. Steps. 模拟题,只要按照向量的顺序,每次走最大的步数就行了,
比赛的时候取最大值的临时变量取错了,系统测试挂了。
C. Pocket Book. 实际上就是求可以组合多少个不同的字符串。
注意到其实每一列的各个字母都是可以互相调换的,其实就是统计
每一列中的不同的字母数,a1,a2,...am
那么结果就是 ans=a1*a2****am.
D.Frames. 一道比较繁琐的几何题。题意大概就是问是否可以找出两个矩形框,并且要求矩形框的边长都要大于3.
先在这里来个连续边框的定义。
定义:连续的边框就是指一串连续的#号组成的串,这个串的长度大于等于3。
其实我们可以观察到,有两个矩形框,其实连续的矩形边框的不同的y坐标最多只有4个,同理,不同的x坐标只有4个。
我们可以先分别找出连续的边框占的x坐标和y坐标。如果连续的边框占的坐标数大于4,就取最
大坐标,最小坐标,次大坐标,次小坐标就行了.
例子1
#####
#. #. #
### .#
#####
连续的x边框占了 1 3 4 这3个坐标
连续的y边框占了 1 3 5 这3个坐标
例子2
####...
####...
####...
####...
####...
对于例子2
连续的x边框占了 1 2 3 4 5 这5个不同的x坐标
连续的y边框占了 1 2 3 4 这4个不同的y坐标
其实这时对于x坐标,我们只需要取 1 2 4 5 这4个不同的坐标就行了。
然后我们由取出的x坐标和y坐标,可以组成最多16个点,这些点都是矩形的顶点,我们只要暴力枚举这两个矩形的端点,再
判断一下就行了。
代码写了一坨。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;
int n,m;
char a[1005][1005];
int b[1005][1005];
vector<int>vx;
vector<int>vy;
struct node
{
int x;
int y;
}p[20];
int lenp=0;
//检查p1,p2两对角点组成的长方形是否联通
bool IsLink(node p1,node p2)
{
int i=0;
for(i=p1.x;i<=p2.x;i++)
{
if(a[i][p1.y]=='#')
b[i][p1.y]=1;
else
break;
}
if(i!=p2.x+1)
return false;
for(i=p1.x;i<=p2.x;i++)
{
if(a[i][p2.y]=='#')
b[i][p2.y]=1;
else
break;
}
if(i!=p2.x+1)
return false;
for(i=p1.y;i<=p2.y;i++)
{
if(a[p1.x][i]=='#')
b[p1.x][i]=1;
else
break;
}
if(i!=p2.y+1)
return false;
for(i=p1.y;i<=p2.y;i++)
{
if(a[p2.x][i]=='#')
b[p2.x][i]=1;
else
break;
}
if(i!=p2.y+1)
return false;
}
bool Is_true()
{
for(int i=0;i<vx.size();i++)
{
for(int j=1;j<=m;j++)
{
if(a[vx[i]][j]=='#' && b[vx[i]][j]==0)
return false;
}
}
for(int i=0;i<vy.size();i++)
{
for(int j=1;j<=n;j++)
{
if(a[j][vy[i]]=='#' && b[j][vy[i]]==0)
return false;
}
}
return true;
}
int main()
{
while(scanf("%d %d",&n,&m)!=EOF)
{
for(int i=1;i<=n;i++)
scanf("%s",a[i]+1);
vx.clear();
vy.clear();
int num1=0;
int num2=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
int temp=0;
while(j<=m && a[i][j]=='#')
{
j+=1;
temp+=1;
}
if(temp>=3)
vx.push_back(i),num1+=1;
}
}
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
int temp=0;
while(j<=n && a[j][i]=='#')
{
j+=1;
temp+=1;
}
if(temp>=3)
vy.push_back(i),num2+=1;
}
}
sort(vx.begin(),vx.end());
sort(vy.begin(),vy.end());
if(num1>4 && num2>4)
{
printf("NO\n");
continue;
}
if(num1>4 )
{
for(int i=1;i<=num1-4;i++)
vx.erase(vx.begin()+2);
}
if(num2>4)
{
for(int i=1;i<=num2-4;i++)
vy.erase(vy.begin()+2);
}
lenp=0;
for(int i=0;i<vx.size();i++)
{
for(int j=0;j<vy.size();j++)
{
lenp+=1;
p[lenp].x=vx[i];
p[lenp].y=vy[j];
}
}
int ok=0,i1=0,j1=0,k1=0,t1=0;
for(int i=1;i<=lenp && ok==0;i++) //uperleft1
for(int j=i+1;j<=lenp && ok==0;j++) //lowright1
for(int k=1;k<=lenp && ok==0;k++) //uperleft2
for(int t=k+1;t<=lenp && ok==0;t++) //lowright2
{
if(p[j].x-p[i].x<2 || p[j].y-p[i].y<2 || p[t].x-p[k].x<2 || p[t].y-p[k].y<2)
continue;
memset(b,0,sizeof(b));
if(IsLink(p[i],p[j])==false || IsLink(p[k],p[t])==false)
continue;
if(Is_true()==false)
continue;
ok=1,i1=i,j1=j,k1=k,t1=t;
}
if(ok==0)
printf("NO\n");
else
{
printf("YES\n");
printf("%d %d %d %d\n",p[i1].x,p[i1].y,p[j1].x,p[j1].y);
printf("%d %d %d %d\n",p[k1].x,p[k1].y,p[t1].x,p[t1].y);
}
}
return 0;
}
E.Garden
生成树问题 Minimal Steiner Tree
具体的解释可以见我的一篇文章 。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <cmath>
#include <vector>
using namespace std;
const int inf = 1000000000;
const int N = 205; //总顶点数
const int A = 7 ; //要包含的顶点数
int sx[4]={0,0,1,-1};
int sy[4]={1,-1,0,0};
int id[A]; //包含顶点的序号
int d[N][N]; //距离矩阵
int r[N][N];
int dp[1<<A][N]; //dp[i][j]表示点j到联通的集合i的最短距离
int path[1<<A][N];
int submask1[1<<A][N];
int submask2[1<<A][N];
int val[N][N];
int px[N];
int py[N];
char str[N][N];
void DrawMap(int d1,int d2)
{
if(r[d1][d2]==d1 || r[d1][d2]==d2)
{
str[px[d1]][py[d1]]='X';
str[px[d2]][py[d2]]='X';
return ;
}
//str[px[d1]][py[d1]]='X';
//str[px[d2]][py[d2]]='X';
str[px[r[d1][d2]]][py[r[d1][d2]]]='X';
DrawMap(d1,r[d1][d2]);
DrawMap(r[d1][d2],d2);
}
void PrintRoute(int mask,int mk)
{
if(mask==1 || mask==2 || mask==4 || mask==8 || mask==16 || mask==32 || mask==64 || mask==128)
{
DrawMap(path[mask][mk],mk);
return ;
}
if(path[mask][mk]!=-1)
{
DrawMap(path[mask][mk],mk);
PrintRoute(submask1[mask][mk],path[mask][mk]);
return ;
}
PrintRoute(submask1[mask][mk],mk);
PrintRoute(submask2[mask][mk],mk);
}
//返回最小值
int Steiner(int n,int a)
{
int top = 1<<a;
for(int k=0;k<n;k++) //vertex 0---n-1
{
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(d[i][j]>d[i][k]+d[k][j]-val[px[k]][py[k]])
{
d[i][j]=d[i][k]+d[k][j]-val[px[k]][py[k]];
r[i][j]=k;
}
}
}
}
for(int i=0;i<top;i++)
{
for(int j=0;j<n;j++)
{
dp[i][j]=inf;
path[i][j]=-1;
}
}
for(int i=0;i<a;i++)
{
for(int j=0;j<n;j++)
{
dp[1<<i][j]=d[id[i]][j];
path[1<<i][j]=id[i];
}
}
for(int i=1;i<top;i++)
{
if((i&(i-1))==0)
continue;
for(int k=0;k<n;k++) //init
{
for(int j=1;j<i;j++)
{
if((i|j)==i && dp[i][k]>dp[j][k]+dp[i-j][k]-val[px[k]][py[k]])
{
dp[i][k]=dp[j][k]+dp[i-j][k]-val[px[k]][py[k]];
path[i][k]=-1;
submask1[i][k]=j;
submask2[i][k]=i-j;
}
}
}
for(int j=0;j<n;j++) //update
{
for(int k=0;k<n;k++)
{
if(dp[i][j]>dp[i][k]+d[k][j]-val[px[k]][py[k]])
{
dp[i][j]=dp[i][k]+d[k][j]-val[px[k]][py[k]];
path[i][j]=k;
submask1[i][j]=i;
}
}
}
}
int ans = inf;
int mk=-1;
for(int i=0;i<n;i++)
{
if(ans > dp[top-1][i])
{
ans=dp[top-1][i];
mk=i;
}
}
PrintRoute(top-1,mk);
return ans;
}
int main()
{
int n,m,k,x,y;
while(scanf("%d %d %d",&n,&m,&k)!=EOF)
{
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
scanf("%d",&val[i][j]);
str[i][j]='.';
px[i*m+j]=i;
py[i*m+j]=j;
}
for(int i=0;i<k;i++)
{
scanf("%d %d",&x,&y);
id[i]=(x-1)*m+y-1;
}
for(int i=0;i<n*m;i++)
for(int j=0;j<n*m;j++)
d[i][j]=inf;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
d[i*m+j][i*m+j]=val[i][j];
r[i*m+j][i*m+j]=i*m+j;
for(int t=0;t<4;t++)
{
int fx=i+sx[t];
int fy=j+sy[t];
if(fx>=0 && fx<n && fy>=0 && fy<m)
{
d[fx*m+fy][i*m+j]=d[i*m+j][fx*m+fy]=val[i][j]+val[fx][fy];
r[fx*m+fy][i*m+j]=r[i*m+j][fx*m+fy]=i*m+j;
}
}
}
}
printf("%d\n",Steiner(n*m,k));
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
printf("%c",str[i][j]);
}
printf("\n");
}
}
return 0;
}