2013-06-19没有注册:没有去做做题,不知道对不对,还没在TopCoder上做过题。
----------------------------------------------------------------------------------------------------
看成是N(N= String.length *String.length)个点无向图;每个顶点有与其相邻的cell的边
即变成寻找图中所有点对的最短路径,(没有负权回路的最短路径是可以动态规划的,Wall-shell算法(希望没写错)复杂度O(N^3),也可以进行N次Dijkstra计算,使用Dijkstra算法可以用双向Dijkstra )
Alic需要选择的是所有点对的路径中的,某个点的最长路径最小的点既可(从图中看,即图的中心,到达其他点的最短路径的最大值最小)
在实际搜索过程中,可以增加 分支限界的过程,如Cost(p1,p2)>MIN_VALUE,即可终止,这样应该对算法实际效率提高很多。
|
-------------------------------------------------------------------------------------------------------------------------------------
2013-06-20:今天具体实现 如下,明天继续修改,采用图论中的dijkstra过程试一试
郁闷,折腾了1天也没有搞定耗时,下面的程序能正确输出结果,但是耗时比较长
算法复杂度太高:
O(N^3),N = m*n,m为行数,n为列数,即N = 使用的算法,基本是Floyd-Warshell算法,但是这里有个小区别
int dist = opt[i][k] + opt[k][j] - opt[k][k];
而常见最短路径的算法则是:
int dist = opt[i][k] + opt[k][j];
实现思路:算法主要在game2中实现
将每个cell映射成一个顶点,初始化各顶点的值,并初始化cell与相邻cell的边的值
cell(x,y) = 1 --->opt(x*n+y,x*n+y) =1;
Edge of cell(x,y) cell(x-1,y) = 1 --->opt[x*n+y,(x-1)*n]=1;
public class GameOnBoard {
public static void main(String args[]) {
String cost[][] =
{
{"11",
"10"
},
{
"01",
"10"
},
{
"111001",
"001000",
"111111",
"001111",
"001100",
"001011",
"111001",
"010011"
},
{
"001001101011",
"110011001101",
"111111000001",
"111101010001",
"011100101111",
"110010111000",
"111111110101",
"111011110111",
"111100100011",
"000000000110",
"101011011110",
"011111000111",
"101111001011"
},
{
"110010100101010110100010001100111011",
"001000000110100011010100000001001000",
"011000110111101001011101110111000100",
"111001011000100101111010100110110011",
"111000011101001010000100001010000010",
"111001110010100101000001001100011011",
"111110100111010101100000100111000111",
"011111111100100111111110000001110111",
"110000010101001111100011110000001000",
"010010110111111100011101100000011010",
"110001100001111001101000101110110001",
"110010000111011110000010110111010101",
"100100110101001001101000001101101101",
"001011101101001100111110101111001110",
"111010111111111100110100000011111100",
"110101101000001001000100101011100000",
"011011001011010001001000100000110101",
"011111111100000011010111010011010100",
"111001111110001110001110010100111010",
"000001111000001100101010000001101110",
"010000110000010010111110111000010101",
"100010010100110011000111101001101011",
"111010110001101011010001111101111100",
"000111110000110000000101100101000110",
"110000010111001001110001101010111100",
"011111101101001011011010011111100010",
"110101111101010100110010000011001101",
"101101111001010100101111100001110001",
"000110010100101111011011110010010010",
"110101010011101000111011100000010011",
"110001010001110011010100110000010001",
"111010101100111100100011001101010100",
"011000000000100001011010000100010001",
"100000110110000001010001001111010000",
"100011111110010011011011001110011111",
"101100001111100101001101100000100001",
"010000111011010110011001110011111000",
"100010100111110111001010100101111010",
"000110011110111011111000101000001000"
}
};
GameOnBoard game = new GameOnBoard();
for(int i=0;i<cost.length;i++)
System.out.println(game.optimalChoice(cost[i]));
}
int optimalChoice(String cost[]) {
int M = cost.length;
int N = cost[0].length();
byte matrix[][] = new byte[M ][ N ];
for (int i = 0; i < M; i++) {
for (int k = 0; k < N; k++) {
if (cost[i].charAt(k) == '1') {
matrix[i ][k] = 1;
} else
matrix[i ][k] = 0;
}
}
return game2(matrix,M,N);
}
int game2(byte[][] matrix,int m,int n) {
byte minChooseCost = Byte.MAX_VALUE;
int N = m * n;
byte opt[][] = new byte[N][N];
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
opt[i][j] = Byte.MAX_VALUE;
}
}
for (int i = 0; i < N; i++) {
opt[i][i] = matrix[i / n][i - i / n * n];
}
for (int i = 0; i < N; i++) {
// opt[i][k] 和opt[k][j];是否相邻
int x1 = i / n;
int y1 = i - x1 * n;
int x2;
int y2;
x2 = x1;
y2 = y1 - 1;
if (y2 >= 0) {
int j = x2 * n + y2;
opt[i][j] = (byte) (opt[i][i] + opt[j][j]);
}
y2 = y1 + 1;
if (y2 < n) {
int j = x2 * n + y2;
opt[i][j] = (byte) (opt[i][i] + opt[j][j]);
}
y2 = y1;
x2 = x1 - 1;
if (x2 >= 0) {
int j = x2 * n + y2;
opt[i][j] = (byte) (opt[i][i] + opt[j][j]);
}
x2 = x1 + 1;
if (x2 < m) {
int j = x2 * n + y2;
opt[i][j] = (byte) (opt[i][i] + opt[j][j]);
}
}
for (int k = 0; k < N; k++) {
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
{
int dist = opt[i][k] + opt[k][j] - opt[k][k];
if (dist < opt[i][j])
opt[i][j] = (byte) dist;
}
}
}
}
minChooseCost = Byte.MAX_VALUE;
//byte max[] = new byte[N];
byte max;
for (int i = 0; i < N; i++) {
max=0;
for (int j = 0; j < N; j++) {
if (max < opt[i][j]) {
max = opt[i][j];
}
}
if (minChooseCost > max)
minChooseCost = max;
}
return minChooseCost;
}
}
2013-06-21 终于有所提高了(还将继续提升下):采用了Dijkstra过程,(说起来真丢人,我还算是做A*,Dijkstra的专业人士)
-------------------------------------------------------------------------------------------------------------------------------
import java.util.Comparator;
public class GameOnBoard {
public static void main(String args[]) {
String cost[][] =
{
{
"11",
"10"
},
{
"01",
"10"
},
{
"111001",
"001000",
"111111",
"001111",
"001100",
"001011",
"111001",
"010011"
},
{
"001001101011",
"110011001101",
"111111000001",
"111101010001",
"011100101111",
"110010111000",
"111111110101",
"111011110111",
"111100100011",
"000000000110",
"101011011110",
"011111000111",
"101111001011"
},
{
"110010100101010110100010001100111011",
"001000000110100011010100000001001000",
"011000110111101001011101110111000100",
"111001011000100101111010100110110011",
"111000011101001010000100001010000010",
"111001110010100101000001001100011011",
"111110100111010101100000100111000111",
"011111111100100111111110000001110111",
"110000010101001111100011110000001000",
"010010110111111100011101100000011010",
"110001100001111001101000101110110001",
"110010000111011110000010110111010101",
"100100110101001001101000001101101101",
"001011101101001100111110101111001110",
"111010111111111100110100000011111100",
"110101101000001001000100101011100000",
"011011001011010001001000100000110101",
"011111111100000011010111010011010100",
"111001111110001110001110010100111010",
"000001111000001100101010000001101110",
"010000110000010010111110111000010101",
"100010010100110011000111101001101011",
"111010110001101011010001111101111100",
"000111110000110000000101100101000110",
"110000010111001001110001101010111100",
"011111101101001011011010011111100010",
"110101111101010100110010000011001101",
"101101111001010100101111100001110001",
"000110010100101111011011110010010010",
"110101010011101000111011100000010011",
"110001010001110011010100110000010001",
"111010101100111100100011001101010100",
"011000000000100001011010000100010001",
"100000110110000001010001001111010000",
"100011111110010011011011001110011111",
"101100001111100101001101100000100001",
"010000111011010110011001110011111000",
"100010100111110111001010100101111010",
"000110011110111011111000101000001000"
}
};
GameOnBoard game = new GameOnBoard();
long start = System.currentTimeMillis();
for(int i=0;i<cost.length;i++)
System.out.println(game.optimalChoice(cost[i]));
long end = System.currentTimeMillis();
System.out.print("cost time"+(end-start));
}
int optimalChoice(String cost[]) {
int M = cost.length;
int N = cost[0].length();
byte matrix[][] = new byte[M ][ N ];
for (int i = 0; i < M; i++) {
for (int k = 0; k < N; k++) {
if (cost[i].charAt(k) == '1') {
matrix[i ][k] = 1;
} else
matrix[i ][k] = 0;
}
}
return game(matrix,M,N);
}
int game(byte[][] matrix, int M, int N) {
int max = Integer.MIN_VALUE;
int minChooseCost = Integer.MAX_VALUE;
// Dijkstra process();
MyPriorityQueue pq = new MyPriorityQueue(1023);
PriorityQueueItem[] pool = new PriorityQueueItem[M * N];
for (int i = 0; i < pool.length; i++) {
pool[i] = new PriorityQueueItem();
pool[i].index = i;
}
for (int i = 0; i < M * N; i++) {
pq.Clear();
for (int j = 0; j < pool.length; j++) {
pool[j].clearFlag();
}
PriorityQueueItem item = pool[i];
item.parentIndex = -1;
int x = i / N;
int y = i - x * N;
item.cost = matrix[x][y];
item.index = i;
item.setInOpen();
pq.add(item);
max = Integer.MIN_VALUE;
while (!pq.empty()) {
item = pq.top();
pq.popheap();
item.setNotInOpen();
item.setInClose();
// find the 4 adjacent cell if available,add them to priority
// queue;
//System.out.print(item.cost);
max = item.cost;
// for each adjacent cell, push into priority queue, if possible.
int cell_i = item.index / N;
int cell_j = item.index - cell_i * N;
int cell_2_i = -1;
int cell_2_j = -1;
// cell 1
cell_2_i = cell_i;
cell_2_j = cell_j - 1;
if (cell_2_j >= 0) {
int newNodeCost = matrix[cell_2_i][cell_2_j];
PriorityQueueItem newItem = pool[cell_2_i * N + cell_2_j];
int newCost = item.cost + newNodeCost;
if (!newItem.isInClose()) {
if (newItem.isInOpen()) {
if (newItem.cost > newCost) {
newItem.cost = newCost;
pq.EditItem(newItem);
}
} else {
newItem.cost = newCost;
pq.add(newItem);
newItem.setInOpen();
}
}
}
// cell 2
cell_2_i = cell_i;
cell_2_j = cell_j + 1;
if (cell_2_j < N) {
int newNodeCost = matrix[cell_2_i][cell_2_j];
PriorityQueueItem newItem = pool[cell_2_i * N + cell_2_j];
int newCost = item.cost + newNodeCost;
if (!newItem.isInClose()) {
if (newItem.isInOpen()) {
if (newItem.cost > newCost) {
newItem.cost = newCost;
pq.EditItem(newItem);
}
} else {
newItem.cost = newCost;
pq.add(newItem);
newItem.setInOpen();
}
}
}
// cell 3
cell_2_i = cell_i - 1;
cell_2_j = cell_j;
if (cell_2_i >= 0) {
int newNodeCost = matrix[cell_2_i][cell_2_j];
PriorityQueueItem newItem = pool[cell_2_i * N + cell_2_j];
int newCost = item.cost + newNodeCost;
if (!newItem.isInClose()) {
if (newItem.isInOpen()) {
if (newItem.cost > newCost) {
newItem.cost = newCost;
pq.EditItem(newItem);
}
} else {
newItem.cost = newCost;
pq.add(newItem);
newItem.setInOpen();
}
}
}
// cell 4
cell_2_i = cell_i + 1;
cell_2_j = cell_j;
if (cell_2_i < M) {
int newNodeCost = matrix[cell_2_i][cell_2_j];
PriorityQueueItem newItem = pool[cell_2_i * N + cell_2_j];
int newCost = item.cost + newNodeCost;
if (!newItem.isInClose()) {
if (newItem.isInOpen()) {
if (newItem.cost > newCost) {
newItem.cost = newCost;
pq.EditItem(newItem);
}
} else {
newItem.cost = newCost;
pq.add(newItem);
newItem.setInOpen();
}
}
}
}
//System.out.println("\n------------------"+i+"will be "+max);
// the maximum value can found,minmize it
if (minChooseCost > max)
minChooseCost = max;
}
return minChooseCost;
}
int game2(byte[][] matrix,int m,int n) {
byte minChooseCost = Byte.MAX_VALUE;
int N = m * n;
byte opt[][] = new byte[N][N];
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
opt[i][j] = Byte.MAX_VALUE;
}
}
for (int i = 0; i < N; i++) {
opt[i][i] = matrix[i / n][i - i / n * n];
}
for (int i = 0; i < N; i++) {
// opt[i][k] 和opt[k][j];是否相邻
int x1 = i / n;
int y1 = i - x1 * n;
int x2;
int y2;
x2 = x1;
y2 = y1 - 1;
if (y2 >= 0) {
int j = x2 * n + y2;
opt[i][j] = (byte) (opt[i][i] + opt[j][j]);
}
y2 = y1 + 1;
if (y2 < n) {
int j = x2 * n + y2;
opt[i][j] = (byte) (opt[i][i] + opt[j][j]);
}
y2 = y1;
x2 = x1 - 1;
if (x2 >= 0) {
int j = x2 * n + y2;
opt[i][j] = (byte) (opt[i][i] + opt[j][j]);
}
x2 = x1 + 1;
if (x2 < m) {
int j = x2 * n + y2;
opt[i][j] = (byte) (opt[i][i] + opt[j][j]);
}
}
for (int k = 0; k < N; k++) {
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
{
int dist = opt[i][k] + opt[k][j] - opt[k][k];
if (dist < opt[i][j])
opt[i][j] = (byte) dist;
}
}
}
}
minChooseCost = Byte.MAX_VALUE;
byte max;
for (int i = 0; i < N; i++) {
max=0;
for (int j = 0; j < N; j++) {
if (max < opt[i][j]) {
max = opt[i][j];
}
}
if (minChooseCost > max)
minChooseCost = max;
}
return minChooseCost;
}
static class PriorityQueueItem implements Comparable<PriorityQueueItem>,Comparator<PriorityQueueItem>{
@Override
public int hashCode(){
return index;
}
public boolean equals( PriorityQueueItem e){
return e!=null &&index==e.index;
}
int index;
int parentIndex;
int cost;
byte flag;
public void setInOpen(){
flag |=1;
}
public void setNotInOpen() {
flag &=~1;
}
public void setInClose(){
flag |=2;
}
public boolean isInOpen(){
return (flag &1)!=0;
}
public boolean isInClose(){
return (flag &2)!=0;
}
public void clearFlag(){
flag =0;
}
@Override
public int compareTo(PriorityQueueItem item) {
if(cost == item.cost)return 0;
if(cost<item.cost) return -1;
return 1;
}
@Override
public int compare(PriorityQueueItem o1, PriorityQueueItem o2) {
if(o1==null ||o2==null)
throw new IllegalArgumentException("cannot be null.");
return o1.compareTo(o2);
}
}
static class MyPriorityQueue{
public MyPriorityQueue(int maxSize)
{
this.maxSize = maxSize;
this.data = new PriorityQueueItem[maxSize+1];
cur = 0;
};
void Clear()
{
cur=0;
}
boolean empty(){return cur==0;}
PriorityQueueItem top(){
return data[1];
}
PriorityQueueItem popheap() {
data[1] = data[cur];
cur--;
adjustify(1);
return data[cur+1];
}
void pushheap(PriorityQueueItem elem)
{
cur = cur+1;
if(cur == maxSize)
{
maxSize <<=1;
PriorityQueueItem []pTempData = new PriorityQueueItem [maxSize];
System.arraycopy(pTempData,0,this.data,1,cur);
data = pTempData;
}
int key = cur;
int i;
data[key] = elem;
i = parent(key);
//adjustify(key);
while(i>0)
{
if(elem.compareTo(data[i])<0)
{
//swap i,key
data[0] = data[i];
data[i] = elem;
data[key] = data[0];
key = i;
i = parent(i);
}
else break;
}
}
boolean EditItem(PriorityQueueItem pItem)
{
//对象必须存在
data[0] = pItem;
int i = cur;
for( ;!data[i].equals(data[0]) ;i--);
if(i==0)
{
//没有找到这个元素那么就把这个元素当作新的元素加进来
this.pushheap(pItem);
}
else
{
//找到这个元素 修改它的值
//data[i]->m_dDisToStart = pItem->m_dDisToStart;
//data[i]->m_dSpeed = pItem->m_dSpeed;
//data[i]->m_lWeight = pItem->m_lWeight;
//data[i]->m_pNext = pItem->m_pNext;
//data[i]->m_pParentArcItem = pItem->m_pParentArcItem;
Update(i);
}
return true;
}
void makeheap()
{
//建堆
for (int i = cur/ 2; i >= 1; i--)
{
adjustify(i);
}
}
int getSize(){return cur;}
void makeheap(PriorityQueueItem []data,int size)
{
System.arraycopy(data,0,this.data,1,size);
cur = size;
//建堆
for (int i = cur/ 2; i >= 1; i--)
{
adjustify(i);
}
}
public int parent(int i) { return i / 2; }
public int left(int i) { return i * 2; }
public int right(int i) { return i * 2 + 1; }
//这个是值变小了,向上调整
int Update(int i)
{
data[0] = data[i];//做一个哨兵
int par = parent(i);
while(data[i].compareTo(data[par])<0)
{
//如果子更小,交换
data[i] = data[par];
data[par] = data[0];
i = par;
par = parent(i);
}
return i;
}
//向下调整
void adjustify(int i)
{
int l = left(i);
int r = right(i);
int smallest = i;
if (l <= cur && data[l].compareTo(data[smallest])<0)
smallest = l;
if (r <= cur && data[r].compareTo(data[smallest])<0)
smallest = r;
if (smallest != i)
{
//swap(data[smallest], data[i]);
data[0] = data[smallest];
data[smallest] = data[i];
data[i] = data[0];
adjustify(smallest);
}
}
PriorityQueueItem[] data;
int maxSize;
int cur;
public void add(PriorityQueueItem item) {
pushheap(item);
}
public PriorityQueueItem poll() {
return popheap();
}
}
}
耗时:(所有列子总耗时1秒中左右,比原来的26秒,快了不少,但还是没达到预期目标要求)
2
1
3
5
7
cost time955