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;
}