Input
第一行有两个整数,N和 M,描述方块的数目。
接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为一个景点;
否则表示控制该方块至少需要的志愿者数目。 相邻的整数用 (若干个) 空格隔开,
行首行末也可能有多余的空格。
Output
由 N + 1行组成。第一行为一个整数,表示你所给出的方案
中安排的志愿者总数目。
接下来 N行,每行M 个字符,描述方案中相应方块的情况:
z ‘_’(下划线)表示该方块没有安排志愿者;
z ‘o’(小写英文字母o)表示该方块安排了志愿者;
z ‘x’(小写英文字母x)表示该方块是一个景点;
注:请注意输出格式要求,如果缺少某一行或者某一行的字符数目和要求不
一致(任何一行中,多余的空格都不允许出现) ,都可能导致该测试点不得分。
Sample Input
4 4
0 1 1 0
2 5 5 1
1 5 5 1
0 1 1 0
Sample Output
6
xoox
___o
___o
xoox
Hint
对于100%的数据,N,M,K≤10,其中K为景点的数目。输入的所有整数均在[0,2^16]的范围内
题解
显然斯坦纳树(好像也可以插头DP)
怎么输出方案呢?
记录一下每个点是从哪个点转移过来的即可
最后输出方案的时候用一个dfs,怎么转移过来的,就怎么dfs回去
(WA了一次是因为输出了大写的X,一定要小心大小写)
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define N 15
const int INF=0x3f3f3f3f;
int dx[4]={1,-1,0,0},dy[4]={0,0,1,-1};
struct node{
int x,y,s;
node(){}
node(int a,int b,int c){x=a;y=b;s=c;}
}u,v;
int f[N][N][1<<10];
node pre[N][N][1<<10],pos[N];
int a[N][N],ans[N][N];
queue<node> q;bool inq[N][N];
void dfs(node i)
{
if(!i.x)return;
ans[i.x][i.y]=1;
node j=pre[i.x][i.y][i.s];
dfs(j);
if(i.x==j.x&&i.y==j.y)dfs(node(i.x,i.y,i.s^j.s));
}
int main()
{
int n,m,k=0,i,j,s,t,l;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
scanf("%d",&a[i][j]);
if(!a[i][j]){k++;pos[k]=node(i,j,0);}
}
}
memset(f,0x3f,sizeof(f));
int all=(1<<k)-1;
for(i=1;i<=n;i++)for(j=1;j<=m;j++)f[i][j][0]=0;
for(i=1;i<=k;i++)f[pos[i].x][pos[i].y][1<<(i-1)]=0;
for(s=1;s<=all;s++){
for(i=1;i<=n;i++)for(j=1;j<=m;j++)
for(t=(s-1)&s;t;t=(t-1)&s){
if(f[i][j][s]>f[i][j][t]+f[i][j][s^t]-a[i][j]){
f[i][j][s]=f[i][j][t]+f[i][j][s^t]-a[i][j];
pre[i][j][s]=node(i,j,t);
}
}
for(i=1;i<=n;i++)for(j=1;j<=m;j++)if(f[i][j][s]<INF)
q.push(node(i,j,s)),inq[i][j]=1;
while(!q.empty()){
u=q.front();q.pop();inq[u.x][u.y]=0;
for(l=0;l<4;l++){
v.x=u.x+dx[l];v.y=u.y+dy[l];v.s=u.s;
if(v.x>0&&v.x<=n&&v.y>0&&v.y<=m){
if(f[v.x][v.y][s]>f[u.x][u.y][s]+a[v.x][v.y]){
f[v.x][v.y][s]=f[u.x][u.y][s]+a[v.x][v.y];
pre[v.x][v.y][s]=u;
if(!inq[v.x][v.y])q.push(v),inq[v.x][v.y]=1;
}
}
}
}
}
int mi=INF;node ss;
for(i=1;i<=n;i++)for(j=1;j<=m;j++)
if(f[i][j][all]<=mi){
mi=f[i][j][all];
ss=node(i,j,all);
}
printf("%d\n",mi);
dfs(ss);
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
if(!a[i][j])printf("x");
else if(ans[i][j])printf("o");
else printf("_");
}
printf("\n");
}
}