Codeforces Round #108 (Div. 2)

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


 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章