先来几张效果图:
问题描述: 有一个的棋盘,和一个坏点,问能否用若干个由三个小方格组成的"L"形的物体覆盖完整个棋盘(不包括坏点)
解决思路: 这是一个分治的典型问题,唔~刚好是作业~.因为棋盘可以均分成四个部分,左上角,左下角,右上角和右下角,坏点必定在其中一个部分,可以发现,分割后的每一个正方形仍然可以分割,直至其大小为 2 X 2.在分割过程中,四个正方形交界处有四个小方格,假设坏点在正方形 A 中则把四个小方格中属于 正方形B和C和D中的交界处小方格也当作坏点,这样,分割到最后 2 X 2 的时候必然有一个坏点,剩余的三个小方格刚好组成一个 "L" 形.
下面是代码:
首先是主函数,创建一个窗体负责接收输入信息,运行结果是上面左图.
package code;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
class asdfghjkl implements ActionListener
{
JFrame jf = new JFrame("棋盘覆盖") ;
JButton re = new JButton("重置") ;
JButton next = new JButton("下一步") ;
JButton ok = new JButton("演示") ;
JButton cl = new JButton("关闭") ;
JLabel posx = new JLabel("横坐标") ;
JLabel posy = new JLabel("纵坐标") ;
JLabel hesize = new JLabel("棋盘大小(1-5)") ;
JTextField tx = new JTextField() ;
JTextField ty = new JTextField() ;
JTextField sz = new JTextField() ;
public asdfghjkl() {
// TODO Auto-generated constructor stub
jf.setSize(300, 200);
jf.setResizable(false) ;
jf.setLayout(new GridLayout(4, 2));
jf.add(hesize) ;
jf.add(sz) ;
jf.add(posx) ;
jf.add(tx) ;
jf.add(posy) ;
jf.add(ty) ;
ok.addActionListener(this);
re.addActionListener(this);
jf.add(ok) ;
jf.add(re) ;
jf.setVisible(true);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Init() ;
}
private void Init() {
// TODO Auto-generated method stub
tx.setText(null);
ty.setText(null);
sz.setText(null);
}
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if (e.getSource().equals(ok)) {
if (sz.getText().equals("") || tx.getText().equals("") || ty.getText().equals("")) {
JOptionPane.showMessageDialog(jf,"error" ,"error input",JOptionPane.ERROR_MESSAGE);
}
int chesssize = 1 , k = Integer.valueOf(sz.getText()) ;
int x = Integer.valueOf(tx.getText()) , y = Integer.valueOf(ty.getText()) ;
if (k < 1 || k > 5) {
JOptionPane.showMessageDialog(jf,"error" ,"error input",JOptionPane.ERROR_MESSAGE);
}// <span style="font-family:KaiTi_GB2312;">保证输入信息都是有效的</span>
for (int i = 1 ; i <= k ; ++ i) chesssize *= 2 ;
REC sb = new REC(1,1,chesssize) ;
REC sa = new REC(x,y,0) ;
if (!sb.baohan(sa)) {
JOptionPane.showMessageDialog(jf,"error" ,"error input",JOptionPane.ERROR_MESSAGE);
}
new Mydialog(jf,chesssize,sa) ;
}
else if (e.getSource().equals(re)) {
Init();
}
}
}
public class Work {
public static void main(String[] agrs) {
String lookAndFeel = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
try {
UIManager.setLookAndFeel(lookAndFeel) ;
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException
| UnsupportedLookAndFeelException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
new asdfghjkl();
TimeCount x = new TimeCount() ;
x.start();
}
}
下面是主函数中用到的几个自定义类
- REC 表示一个起点是(x,y),长度是 len 的正方形.
- MyDialog 表示弹出一个对话框,owner 是主函数中的jframe
- TimeCount 表示一个每个100 ms 执行一次justshownext的线程
REC:
package code;
class REC
{
public int x , y , len ;
public REC() {
// TODO Auto-generated constructor stub
this.x = this.y = this.len = 0 ;
}
public REC(REC rt) {
this.x = rt.x ;
this.y = rt.y ;
this.len = rt.len ;
}
public REC(int x,int y,int len) {
this.x = x ;
this.y = y ;
this.len = len ;
}
public boolean baohan(REC rec) {
if (rec.x >= this.x && rec.x <= (this.x+this.len-1) && rec.y >= this.y && rec.y <= (this.y+this.len-1)) return true ;
return false ;
}
public boolean baohan(REC rec[],int cnt) {
for (int i = 0 ; i < cnt ; ++ i) {
if (this.baohan(rec[i])) return true ;
}
return false;
}
}
TimeCount
package code;
class TimeCount extends Thread
{
long timesec ;
public TimeCount() {
timesec = 0;
}
public void run() {
while (true) {
try {
if (Mydialog.ok) Mydialog.justshownext() ;
Thread.sleep(100);
}
catch (Exception e) {}
}
}
}
MyDialog
package code;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
class Mydialog implements ActionListener
{
JButton up = new JButton("上一步") ;
JButton ne = new JButton("下一步") ;
JButton cl = new JButton("关闭") ;
JButton be = new JButton("开始") ;
JButton sp = new JButton("暂停") ;
JFrame jf = new JFrame() ;
JDialog diacp ;
static int vis[][] = new int[33][33] ;
static JLabel[][] chess ;
static int chesssize ;
int cnt = 0;
static int k = 0;
static int nowk = 0;
int xxx = 1 ;
public static boolean ok = false ;
REC pos ;
REC[] rec ;
@SuppressWarnings("static-access")
public Mydialog(JFrame jf,int chesssize,REC pos) {
this.chesssize = chesssize ;
this.jf = jf ;
this.pos = pos ;
nowk = k = cnt = 0 ;
rec = new REC[chesssize*chesssize+1] ;
rec[cnt++] = new REC(pos) ;
diacp = new JDialog(jf, "演示", true) ;
Init() ;
}
private void Init() {
// TODO Auto-generated method stub
Container cp = diacp.getContentPane() ;
JPanel pa1 = new JPanel(new FlowLayout());
ne.addActionListener(this);
up.addActionListener(this);
cl.addActionListener(this);
be.addActionListener(this);
sp.addActionListener(this);
pa1.add(be) ;
pa1.add(sp) ;
pa1.add(ne) ;
pa1.add(up) ;
pa1.add(cl) ;
JPanel pa2 = new JPanel(new GridLayout(chesssize,chesssize)) ;
chess = new JLabel[chesssize+1][chesssize+1] ;
for (int i = 1 ; i <= chesssize ; ++ i) {
for (int j = 1 ; j <= chesssize ; ++ j) {
chess[i][j] = new JLabel() ;
vis[i][j] = -1;
chess[i][j].setOpaque(true);
chess[i][j].setBackground(Color.white);
pa2.add(chess[i][j]) ;
}
}
chess[pos.x][pos.y].setBackground(Color.black);
vis[pos.x][pos.y] = -2 ;
cp.add(pa1, BorderLayout.NORTH);
cp.add(pa2, BorderLayout.CENTER);
diacp.setSize(500, 500);
diacp.setVisible(true);
}
void presolve(REC rt) {
// TODO Auto-generated method stub
if (rt.len == 2) {
for (int i = rt.x ; i < rt.x + rt.len ; ++ i) {
for (int j = rt.y ; j < rt.y + rt.len ; ++ j) {
if (vis[i][j] == -1) {
vis[i][j] = k ;
}
}
}
k ++ ;
}
else {
REC[] A = new REC[5] ;
REC[] B = new REC[5] ;
A[1] = new REC(rt.x,rt.y,rt.len/2) ;// left and up
A[2] = new REC(rt.x,rt.y+rt.len/2,rt.len/2) ; //right and up
A[3] = new REC(rt.x+rt.len/2,rt.y,rt.len/2) ; // left and down
A[4] = new REC(rt.x+rt.len/2,rt.y+rt.len/2,rt.len/2) ; // right and down
B[1] = new REC(A[4].x-1,A[4].y-1,0) ;
B[3] = new REC(A[4].x,A[4].y-1,0) ;
B[2] = new REC(A[4].x-1,A[4].y,0) ;
B[4] = new REC(A[4].x,A[4].y,0) ;
for (int i = 1 ; i <= 4 ; ++ i) {
if (A[i].baohan(rec, cnt)) {
for (int j = 1 ; j <= 4 ; ++ j) {
if (i != j) {
rec[cnt++] = new REC(B[j]) ;
vis[B[j].x][B[j].y] = -2 ;
}
}
break ;
}
}
for (int i = 1 ; i <= 4 ; ++ i) {
presolve(A[i]);
}
}
}
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if (e.getSource().equals(cl)) {
diacp.dispose();
}
else if (e.getSource().equals(ne)) {
justshownext() ;
}
else if (e.getSource().equals(up)) {
justshowup() ;
}
else if (e.getSource().equals(be)) {
if (xxx == 1) {
nowk = 0 ;
presolve(new REC(1,1,chesssize)) ;
xxx = 2 ;
}
if (!ok) {
ok = true ;
}
}
else if (e.getSource().equals(sp)) {
ok = false ;
}
}
private void justshowup() {
// TODO Auto-generated method stub
if (nowk < 0) return ;
for (int i = 1 ; i <= chesssize ; ++ i) {
for (int j = 1; j <= chesssize ; ++ j) {
if (vis[i][j] == nowk-1) {
chess[i][j].setBackground(Color.white);
}
}
}
nowk -- ;
}
static void justshownext() {
// TODO Auto-generated method stub
Color op = new Color(
(new Double(Math.random() * 128)).intValue() + 128,
(new Double(Math.random() * 128)).intValue() + 128,
(new Double(Math.random() * 128)).intValue() + 128);
if (nowk <= k) {
for (int i = 1 ; i <= chesssize ; ++ i) {
for (int j = 1 ; j <= chesssize ; ++ j) {
if (vis[i][j] == nowk) {
chess[i][j].setBackground(op) ;
}
}
}
nowk ++ ;
}
}
}
~end~