4148:[AMPPZ2014]Pillars
时间限制: 1000 ms 内存限制: 262144 KB
【题目描述】
给定一个n*m的矩形,其中有f个2*2的障碍物,其中任意两个障碍物中心之间的欧几里得距离至少为6,且每个障碍物的中心到边缘的距离至少为3。请找到一条从左下角(1,1)出发经过所有没有障碍物的点各一次的且最后回到左下角的回路。
【输入】
第一行包含三个整数n,m,f(1≤n,m≤1000且n,m都为偶数)。
接下来f行,每行两个整数x,y(1≤x<n,1≤y<m),表示该障碍物左下角的坐标。
【输出】
如果无解,输出NIE,否则第一行输出TAK,第二行输出方案。
方案包含n*m-4*f个字符,第i个字符表示第i步的移动方向,用G表示上,D表示下,L表示左,P表示右。
【输入样例】
12 6 2
3 3
9 3
【输出样例】
TAK
PPPPPPPPPPPGGGLDDLLLLLGPPGLLLDDLLLGGGPPPPPPPPPPGLLLLLLLLLLLDDDDD
【提示】
【思路分析】
今天才知道原来OI题还分为判断题,计数题,最值题,构造题,其中计数与最值是高中OI考察最多的,但是我们也不能忽视另外两个啊,所以你应该知道这道题是构造题了吧(显然不是判断题嘛。。。)
构造题一般有多种解法:
1.传统法
多用于最短路,DP,可以直接记录转移路径
2.增量法
在原有基础上增加一些限制信息,在对原本的构造进行修改
3.多项式法
我也不知道。。。
这道题显然我们可以用增量构造的方法,假设我们没有障碍,构造一个满足条件的方案。根据题意,我们的障碍之间的距离不会小于3,所以我们可以将每个障碍放在一个6*6的矩形中当做一个单位,并且单位之间不会影响,我们每次新加入一个障碍会发现我们只需要修改一部分方格中的信息,直接修改即可。值得注意的是,由于我们最后要回去,所以我们要预留一条回去的路径,这里我留的是最下面的一行,这里如果加入的障碍所在单位中对最下面一行产生了影响那就要特判修改了,具体看代码。
最后吐槽一下:我居然在一个没有SPJ的网站上交了半天。。。但BZOJ是权限题,mmp。。。想做的可以借个号吧
题目传送门,点不点的开随缘。。。
【代码实现】
1 #include<cstdio> 2 #include<cctype> 3 #include<algorithm> 4 #include<cstring> 5 #include<stack> 6 using namespace std; 7 inline void read(int &v) 8 { 9 int f;char ch; 10 while(!isdigit(ch=getchar())&&ch!='-'); ch=='-'?(f=-1,v=0):(f=1,v=ch-'0'); 11 while(isdigit(ch=getchar())) v=v*10+ch-'0';v=v*f; 12 } 13 const int N=1e3+5; 14 char mp[N][N]; 15 int n,m,k; 16 int main() 17 { 18 read(n),read(m),read(k); 19 for(int i=1;i<=n;i++) 20 for(int j=1;j<=m;j++) 21 { 22 if((i&1)) mp[i][j]='G'; 23 else mp[i][j]='D'; 24 } 25 for(int i=1;i<n;i+=2) mp[i][m]='P'; 26 for(int i=2;i<n;i+=2) mp[i][2]='P'; 27 for(int i=2;i<=n;i++) mp[i][1]='L'; 28 for(int i=1;i<=k;i++) 29 { 30 int x,y; 31 read(x),read(y); 32 // mp[x][y]=mp[x][y+1]=mp[x+1][y]=mp[x+1][y+1]=' '; 33 if(x&1) 34 { 35 mp[x+1][y+3]=mp[x][y-1]='P'; 36 mp[x+1][y+2]=mp[x+2][y+2]='L'; 37 } 38 else 39 { 40 if(y>3) 41 { 42 mp[x][y+2]=mp[x+1][y-2]='P'; 43 mp[x+2][y-1]=mp[x+1][y-1]='L'; 44 } 45 else 46 { 47 mp[x][y+2]='P'; 48 mp[x+1][y-2]='G'; 49 mp[x+1][y-1]='L'; 50 mp[x][y-1]='D'; 51 } 52 } 53 } 54 // for(int j=m;j>=1;j--) 55 // { 56 // for(int i=1;i<=n;i++) 57 // printf("%c ",mp[i][j]); 58 // printf("\n"); 59 // } 60 printf("TAK\n"); 61 int x=1,y=1; 62 for(int i=1;i<=n*m-k*4;i++) 63 { 64 printf("%c",mp[x][y]); 65 if(mp[x][y]=='G') y++; 66 else if(mp[x][y]=='D') y--; 67 else if(mp[x][y]=='P') x++; 68 else if(mp[x][y]=='L') x--; 69 } 70 return 0; 71 }