中文意思:
就是在 空的地方(字符'-')建造房子,蓝色房子是100人口,红色房子是200人口(建造红色房子时,旁边必须有蓝色房子),要求人口最大,只需输出可用的解就可以了。k是可行解的步数。
题解:
此题就是将尽可能的建造红色房子,但要求在建造红色房子时,它旁边必须有个蓝色房子。但输出无顺序要求。 首先我们将图分成几块(被#完全隔开)。你可以发现这样一点。你将所有的先全部建造成蓝色,然后再慢慢的从边际(也就是叶子)开始逐个的将此变成红色。看样例3,你就明白了。如此,每块分割开的一个个块将最后变成一个蓝的房子跟红色的其他房子。我们很容易知道,这时居住人口是最多的。因此,DFS即可解决这个问题。
因为n<=m<=500。我们的最大步数是3*m*n<k<=10^6次。所以这样的解是可以的。
我们的k值就是 空房数量*3-蓝色房子(一个块只有1个)*2;k可以直接在DFS时出来(先压点到栈)。
之后不断弹出栈中元素,分别输出 D操作跟R操作即可。。
/* * @author ipqhjjybj * @date 20130705 * */ #include <cstdio> #include <cstring> #include <iostream> #include <stack> #define clr(x,k) memset((x),(k),sizeof(x)) #define MAX(a,b) ((a)>(b)?(a):(b)) using namespace std; char s[505][505]; int n,m; struct node{ int x,y; bool f; //表示是否为一个块的开头 node(){}; node(int xx,int yy,bool first){ x=xx,y=yy,f=first; }; }; stack<node> sn; bool visit[505][505]; int k; int x1[4]={0,0,1,-1}; int y1[4]={1,-1,0,0}; #define legal(x,a) (1<=x&&x<=a) void dfs(int xx,int yy){ int _x,_y,i; for(i=0;i<4;i++){ _x=xx+x1[i],_y=yy+y1[i]; if(legal(_x,n)&&legal(_y,m)&&!visit[_x][_y]&&s[_x][_y]=='.'){ visit[_x][_y]=true; sn.push(node(_x,_y,false)); dfs(_x,_y); } } } int main(){ // freopen("D.in","r",stdin); int i,j; while(scanf("%d %d",&n,&m)!=EOF){ getchar(); for(i=1;i<=n;i++) gets(s[i]+1); sn.empty(); k=0; clr(visit,false); for(i=1;i<=n;i++) for(j=1;j<=m;j++){ if(!visit[i][j]&&s[i][j]=='.'){ k-=2; visit[i][j]=true; sn.push(node(i,j,true)); dfs(i,j); } } k+=sn.size()*3; printf("%d ",k); for(i=1;i<=n;i++) for(j=1;j<=m;j++) if(visit[i][j]) printf("B %d %d ",i,j); node t; while(!sn.empty()){ t = sn.top(); sn.pop(); if(!t.f){ printf("D %d %d ",t.x,t.y); printf("R %d %d ",t.x,t.y); } } } return 0; }