time limit: 2000ms
language:ASM、C、C++、C#、Java、VB
Difficulty:★★★★
Describe:
Assume that their are m persons,p cube types and n 3 - dimensional containers.Each cube's length and width are 1 and its height is a positive interger.Each person have several cubes and each cube is belonging to different cube types. Your task is to put these cubes in random different integercoordinates of these container.You should ensure that there isn't any cube which is overlapped with another.
Input:
The first line:Four integers x,y,z,n(0<x,y,z<50,0<n<10)separated by whitespace,denoting the lengths of the 3 - dimensional container on each dimensional and the count of containers;
The following n lines:A single string,denoting the name of each container;
The following line:A single integer (0<p<50),denoting the number of cube types;
The following p lines:The name of cube and a integer q(0<q<=z)separated by whitespace,denoting the height of cube;
The following line:A integer m(0<m<100),denoting the number of persons;
The following m lines:The name of person and several integer separated by whitespace,denoting the cube types belonging to him.
Output:
For each person, print his or her name , followed by the corresponding cube coordinates in the format shown in the Sample Output.
If there is no way to put all the cubes in these containers, output a single line:"No solution!".
Sample Input 1:
2 2 3 2
容器一
容器二
4
第一种方块 2
第二种方块 3
第三种方块 1
第四种方块 2
3
柯南 1 2 3
灰原 3 4
元太 1 2
Sample Output 1:
柯南
第一种方块 容器一(2,1,2)
第二种方块 容器二(1,2,1)
第三种方块 容器一(1,1,2)
灰原
第三种方块 容器二(2,2,1)
第四种方块 容器一(1,2,1)
元太
第一种方块 容器一(2,2,2)
第二种方块 容器二(2,1,1)
Sample Input 2:
2 2 4 1
实验室一
4
J2ME项目设计 1
软件工程实验 2
计算机网络实验 3
算法设计实验 4
3
网络一班 1 2 3
软件一班 1 2
计科一班 1 2 4
Sample Output 2:
网络一班
J2ME项目设计 实验室一(1,2,1)
软件工程实验 实验室一(1,2,2)
计算机网络实验 实验室一(2,2,2)
软件一班
J2ME项目设计 实验室一(1,2,4)
软件工程实验 实验室一(2,1,1)
计科一班
J2ME项目设计 实验室一(2,2,1)
软件工程实验 实验室一(2,1,3)
算法设计实验 实验室一(1,1,1)
Sample Input 3:
2 2 4 1
实验室一
4
J2ME项目设计 1
软件工程实验 2
计算机网络实验 3
算法设计实验 4
3
网络一班 1 2 3
软件一班 2 3
计科一班 1 2 4
Sample Output 3:
No Solution!
Solution:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace RapidPrototyping0_1_1
{
class Program
{
//A point in the 4 - dimensional space
struct point4d
{
public int w, x, y, z;
public point4d(int w, int x, int y, int z)
{
this.w = w;
this.x = x;
this.y = y;
this.z = z;
}
}
//The cube with a specific height
struct cube
{
public int height;
public string name;
public int ownerIndex;
public string owner;
public point4d pt;
}
//The 4 - dimensional space
static int[, , ,] space;
//The cube array
static cube[] cubeArray;
//The names of all the 3 - dimensional container
static string[] containerName;
//Entrance
static void Main(string[] args)
{
using (StreamReader sr = new StreamReader("in.txt", Encoding.GetEncoding("GB2312")))
using (StreamWriter sw = new StreamWriter("out.txt"))
Distribute(sr,sw);
}
//Distribute all the cubes in the 4D space
private static void Distribute(StreamReader sr, StreamWriter sw)
{
int i,x, y, z, w, n, m;
string s = sr.ReadLine();
Distribute_wxyz(s,out x,out y,out z,out w);
space = new int[w,x,y,z];
containerName = new string[w];
for (i = 0; i < w; i++) containerName[i] = sr.ReadLine();
n = Convert.ToInt32(sr.ReadLine());
string[] name = new string[n];
int[] height = new Int32[n];
for (i = 0; i < n; i++)
{
string s1 = sr.ReadLine();
Distribute_nameheight(s1,out name[i],out height[i]);
}
m = Convert.ToInt32(sr.ReadLine());
Distribute_SetCube(m, sr, out cubeArray, name, height);
if (Distribute_BackTrack(0)) Distribute_Output(sw);
else sw.WriteLine("No Solution!");
}
//Extract the value of w,x,y and z from the string
private static void Distribute_wxyz(string s, out int x, out int y, out int z, out int w)
{
string[] sarray = s.Split(' ');
x = Convert.ToInt32(sarray[0]);
y = Convert.ToInt32(sarray[1]);
z = Convert.ToInt32(sarray[2]);
w = Convert.ToInt32(sarray[3]);
}
//Extract the value of name and height from the string
private static void Distribute_nameheight(string s1, out string name, out int height)
{
string[] sarray = s1.Split(' ');
name = sarray[0];
height = Convert.ToInt32(sarray[1]);
}
//Create a certain number of cubes and set their attributes
private static void Distribute_SetCube(int m, StreamReader sr, out cube[] cubeArray,string[] name,int[] height)
{
List<cube> cubelist = new List<cube>();
for (int j = 0; j < m; j++)
{
string s = sr.ReadLine();
string[] sArray = s.Split(' ');
string owner = sArray[0];
for (int i = 0; i < sArray.Length - 1; i++)
cubelist.Add(Distribute_SetCube_New(j, owner, Convert.ToInt32(sArray[i + 1])-1, name, height));
}
cubeArray = Distribute_SetCube_Array(cubelist);
cubeArray = Distribute_SetCube_Remix(cubeArray);
}
//Create a new cube and set its attributes
private static cube Distribute_SetCube_New(int ownindex,string owner, int index, string[] name, int[] height)
{
cube c = new cube();
c.height = height[index];
c.name = name[index];
c.owner = owner;
c.ownerIndex = ownindex;
return c;
}
//Translate the cube list to cube array
private static cube[] Distribute_SetCube_Array(List<cube> cubelist)
{
int count = cubelist.Count;
cube[] cubeArray = new cube[count];
for (int i = 0; i < count; i++) cubeArray[i] = cubelist[i];
return cubeArray;
}
//Calculate the location of all the cubes in 4 - dimensional space using back track algorithm
private static bool Distribute_BackTrack(int p)
{
if (p >= cubeArray.Length) return true;
else
{
point4d[] availableArray = Distribute_BackTrack_Random(cubeArray[p].height);
foreach (point4d pt in availableArray)
{
bool flag = false;
Distribute_BackTrack_Load(ref cubeArray[p], pt);
flag = Distribute_BackTrack(p + 1);
if (flag) return true;
else
Distribute_BackTrack_Unload(cubeArray[p].height, pt);
}
}
return false;
}
//Get all the positions which can put the cube with a specific height and disorganize them
private static point4d[] Distribute_BackTrack_Random(int height)
{
List<point4d> ptlist = new List<point4d>();
for (int i = 0; i < space.GetLength(0); i++)
for (int j = 0; j < space.GetLength(1); j++)
for (int k = 0; k < space.GetLength(2); k++)
for (int l = 0; l < space.GetLength(3) - height + 1; l++)
{
bool putdownable = true;
for (int m = 0; m < height; m++)
if (space[i, j, k, l + m] == 1)
{
putdownable = false;
break;
}
if (putdownable) ptlist.Add(new point4d(i, j, k, l));
}
point4d[] pointArray = Distribute_BackTrack_Random_Array(ptlist);
return pointArray;
}
//Translate the point list to point array
private static point4d[] Distribute_BackTrack_Random_Array(List<point4d> ptlist)
{
int count = ptlist.Count;
point4d[] ptArray = new point4d[count];
for (int i = 0; i < count; i++)
ptArray[i] = ptlist[i];
return ptArray;
}
//Disorganize the cube array
private static cube[] Distribute_SetCube_Remix(cube[] cubeArray)
{
int count = cubeArray.Length;
int[] indexArray = new int[count];
cube[] newArray = new cube[count];
for (int i = 0; i < count; i++)
{
indexArray[i] = Distribute_SetCube_Remix_Index(count, i, indexArray);
newArray[i] = cubeArray[indexArray[i]];
}
return newArray;
}
//Get a random index which haven't appeared
private static int Distribute_SetCube_Remix_Index(int count, int i, int[] indexArray)
{
Random r = new Random();
int result;
do
{
result = r.Next(count);
}
while (Distribute_BackTrack_Random_Remix_Index_Exist(result, indexArray,i));
return result;
}
//Check whether the index is exist
private static bool Distribute_BackTrack_Random_Remix_Index_Exist(int result, int[] indexArray, int i)
{
for (; i > 0; i--)
if (indexArray[i - 1] == result)
return true;
return false;
}
//Put the cube to the specific point of the 4 - dimensional space
private static void Distribute_BackTrack_Load(ref cube cube, point4d pt)
{
for (int i = 0; i < cube.height; i++)
{
space[pt.w, pt.x, pt.y, pt.z + i] = 1;
}
cube.pt = pt;
}
//Remove the specific cube in the 4 - dimensional space
private static void Distribute_BackTrack_Unload(int height, point4d pt)
{
for (int i = 0; i < height; i++)
{
space[pt.w, pt.x, pt.y, pt.z + i] = 0;
}
}
//Output the final result
private static void Distribute_Output(StreamWriter sw)
{
Distribute_Output_SortByOwner(cubeArray);
string owner = "";
for (int i = 0; i < cubeArray.Length; i++)
{
if (cubeArray[i].owner != owner)
{
owner = cubeArray[i].owner;
sw.WriteLine(owner);
}
sw.WriteLine(cubeArray[i].name + " " + containerName[cubeArray[i].pt.w]+"("+(cubeArray[i].pt.x+1)+","+(cubeArray[i].pt.y+1)+","+(cubeArray[i].pt.z+1)+")");
}
}
//Ascending sort the cubes by their owners
private static void Distribute_Output_SortByOwner(cube[] cubeArray)
{
for (int i = 0; i < cubeArray.Length-1; i++)
{
for (int j = i + 1; j < cubeArray.Length; j++)
{
if (cubeArray[i].ownerIndex > cubeArray[j].ownerIndex)
Distribute_Swap(ref cubeArray[i],ref cubeArray[j]);
}
}
}
//Swap two cube
private static void Distribute_Swap(ref cube cube_1, ref cube cube_2)
{
cube temp = cube_1;
cube_1 = cube_2;
cube_2 = temp;
}
}
}