北大ACM试题1009之直观解法(TLE的。。。)

从这题开始,真正是考验水平的时候了。。。折腾了3个晚上,还看了大神的结题思路才AC的,太不容易了。。。先说说题意吧,好多人连题目都看不懂。。。大致的意思是,有一张图片,用图片每行的像素数(2-10^9),还有每个像素的rgb值(0-255)及这个值出现的次数(1-10^9),就可以表示出来,现在有一种算法,是将每个像素的值,减去周围八个格子的值,取绝对值的最大,输出的格式跟输入的格式保持一致。

这道题最大的问题就是数字太大,没法直接开数组暴力,所以略微思考一下就会想到,如果一个像素出现了很多次,只有第一行,第二行,还有倒数第二行,倒数第一行是有变化的,中间的转化之后都是0,根据这个思路,花了一晚上,写了下面的代码。

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Main_1009_old {

public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
List<String> output = new ArrayList<String>();
String width = cin.nextLine();//获得列数
while(!width.equals(“0”)){
output.add(width);//别忘了把列数加入到输出中
int wid = Integer.parseInt(width);
String p = cin.nextLine();
int[][] in = new int[2][1000];
int pair = 0;
int totalPixel = 0;
while(!p.equals(“0 0”)){
int pixel = Integer.parseInt(p.split(” “)[0]);//像素
int number = Integer.parseInt(p.split(” “)[1]);//像素个数
in[0][pair] = pixel;
in[1][pair] = number;
pair++;
totalPixel += number;
p = cin.nextLine();
}
int pos = 1;
List<String> outputTemp = new ArrayList<String>();
for(int i=0;i<pair;i++){
int start_row = (pos-1)/wid;
int start_col = (pos-1)%wid;
int end_row = (pos+in[1][i]-1)/wid;
int end_col = (pos+in[1][i]-1)%wid;
//总的行数小于4行
if(end_row – start_row < 4){
pos = addTempMaxPixel(outputTemp,in[1][i],pos,in,wid,totalPixel);
}else{
pos = addTempMaxPixel(outputTemp,wid*2 – start_col,pos,in,wid,totalPixel);
//超过4行的部分都是0
outputTemp.add(“0 “+wid*(end_row – start_row – 3));
pos += wid*(end_row – start_row – 3);
pos = addTempMaxPixel(outputTemp,wid + end_col,pos,in,wid,totalPixel);
}
}
int i=0;
while(i < outputTemp.size()){
//把临时的文件,相同的像素进行合并
int pixel = Integer.parseInt(outputTemp.get(i).split(” “)[0]);
int count = Integer.parseInt(outputTemp.get(i).split(” “)[1]);
int j = i+1;
while(j < outputTemp.size()){
if(Integer.parseInt(outputTemp.get(j).split(” “)[0]) == pixel){
count += Integer.parseInt(outputTemp.get(j).split(” “)[1]);;
j++;
}else{
break;
}
}
i = j;
output.add(pixel+” “+count);
}
output.add(“0 0”);
width = cin.nextLine();
}
output.add(“0”);
cin.close();
for(int i=0;i<output.size();i++){
System.out.println(output.get(i));
}
}

//获得每个格子转换之后的像素值
public static int getMaxPixel(int pos,int[][] in,int wid,int totalPixel){
int pixel = getPixelByPos(pos,in);
int maxPixel = 0;

int row = (pos-1)/wid;
int col = (pos-1)%wid;
for(int i=row-1;i<=row+1;i++){
for(int j=col-1;j<=col+1;j++){
int tempPos = i*wid + j + 1;
if(i<0 || j<0 || j>=wid || tempPos>=totalPixel){
continue;
}
int tempPixel = getPixelByPos(tempPos,in);
if(maxPixel < Math.abs(tempPixel-pixel)){
maxPixel = Math.abs(tempPixel-pixel);
}
}
}
return maxPixel;
}

//通过position来获得像素值
public static int getPixelByPos(int pos,int[][] in){
int i=0,j=0;
while(i < pos){
i += in[1][j++];
}
return in[0][j-1];
}

//把长度为length的像素值进行转换
public static int addTempMaxPixel(List<String> outputTemp,int length,
int pos,int[][] in,int wid,int totalPixel){
int j=0;
while(j < length){
int pixel = getMaxPixel(pos,in,wid,totalPixel);
int count = 1;
int k = j+1;
pos++;
while(k < length){
if(getMaxPixel(pos,in,wid,totalPixel) == pixel){
count ++;
k++;
pos++;
}else{
break;
}
}
j = k;
outputTemp.add(pixel+” “+count);
}
return pos;
}
}

结果提交上去是TLE的。。。仔细想想才发现,原来每行的像素个数可以是10^9的!!这样如果来个4行,那就必然超时了。。。正确答案详见下篇。。。

点赞