P6285题解,来了!
思路
无聊的模拟题(COCI的原题),打起来有点烦。
在这里使用dp的方法实现比较方便。
设dpi,jdp_{i,j}dpi,j为Mirko当前是否可以到达所定义位置(i,j)(i,j)(i,j)。 转移方程如下(伪代码)
dpi,j=dpi,j−1∣dpi+1,j−1(i=1)dp_{i,j}=dp_{i,j-1}|dp_{i+1,j-1}(i=1)dpi,j=dpi,j−1∣dpi+1,j−1(i=1)
dpi,j=dpi+1,j−1∣dpi−1,j−1(2≤i≤9)dp_{i,j}=dp_{i+1,j-1}|dp_{i-1,j-1}(2≤i≤9)dpi,j=dpi+1,j−1∣dpi−1,j−1(2≤i≤9)
dpi,j=dpi,j−1∣dpi−1,j−1(i=10)dp_{i,j}=dp_{i,j-1}|dp_{i-1,j-1}(i=10)dpi,j=dpi,j−1∣dpi−1,j−1(i=10)
输出方案按照题意模拟即可,这里不细聊。
复杂度:O(n2)O(n^2)O(n2)
上AC代码
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 100000//宏定义
int n,cnt;
char mp[11][MAXN+5];
int dp[11][MAXN+5];
int vis[MAXN+5];
void print(int x,int y)
{
if(x==10&&dp[x][y-1])print(x,y-1);
else if(x==10&&dp[x-1][y-1])print(x-1,y-1);
else if(x==1&&dp[x][y-1]){vis[y-1]=1;print(x,y-1);}
else if(x==1&&dp[x+1][y-1]){vis[y-1]=1;print(x+1,y-1);}
else if(dp[x-1][y-1])print(x-1,y-1);
else if(dp[x+1][y-1]){vis[y-1]=1;print(x+1,y-1);}
else return ;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=10;i++)
scanf("%s",mp[i]+1);
for(int i=1;i<=10;i++)
for(int j=1;j<=n;j++)
dp[i][j]=0;
if(mp[10][1]!='X')dp[10][1]=1;
for(int j=2;j<=n;j++)
for(int i=1;i<=10;i++)
if(mp[i][j]!='X')
{
if(i==1)dp[i][j]|=dp[i][j-1],dp[i][j]|=dp[i+1][j-1];
else if(i==10)
dp[i][j]|=dp[i][j-1],dp[i][j]|=dp[i-1][j-1];
else dp[i][j]|=dp[i-1][j-1],dp[i][j]|=dp[i+1][j-1];
}
for(int i=1;i<=10;i++)
if(dp[i][n]){print(i,n);break;}
for(int i=1;i<=n;i++)
{
int p=i;
while(vis[p])p++;if(vis[i])cnt++;i=p;}
printf("%d\n",cnt);
for(int i=1;i<=n;i++)
{
int p=i;
while(vis[p])p++;
if(vis[i])printf("%d %d\n",i-1,p-i);
i=p;
}
}
注意点
在这里我没有打注释,是希望大家能够通过我的思路来自己理解,而不是对着注释傻傻的看一遍,或者是直接复制粘贴,为了维护洛谷社区秩序,勿抄题解!