http://poj.org/problem?id=2895
//Version 1
#include <iostream>
#include <stdlib.h>
#include <string.h>
int No_2895();
int main(int argc, char** argv) {
No_2895();
return 0;
}
int No_2895(){
int testCaseNumber;
int p,w;
int result;
char preChar;
char curChar;
char preCharFlag = '0'; //FLAG, 标识字符是否属于A到Z; 0表述不属于,1表示属于;
char curCharFlag = '1';
int pressTimes = 0;
char LookupTable[26]={ //字母相关关系表,例如映射A为0,B为1,通过查表,可以知道A和B 都对应‘2’
'2','2','2',// A,B,C
'3','3','3',// D,E,F
'4','4','4',// G,H,I
'5','5','5',// J,K,L
'6','6','6',//M,N,O
'7','7','7','7',//P,Q,R,S
'8','8','8', //T,U,V
'9','9','9','9' //W,X,Y,Z
};
int inputCountTable[26]={ //按键次数查询表
1,2,3,// A,B,C
1,2,3,// D,E,F
1,2,3,// G,H,I
1,2,3,// J,K,L
1,2,3,//M,N,O
1,2,3,4,//P,Q,R,S
1,2,3, //T,U,V
1,2,3,4, //W,X,Y,Z
};
scanf("%d",&testCaseNumber);
while(testCaseNumber--){
scanf("%d %d\n",&p,&w);
result = 0;
preChar = ' '; // 每次输入新的一行字符前,将第一个字符的preChar(前一个字符)设置成空格;
preCharFlag = '0'; //FLAG, 标识字符是否属于A到Z; 0表述不属于,1表示属于;
curCharFlag = '1';
//Todo:
//这里可以进一步改进一下:对于输入字符串,不用getchar,减少调用IO的次数,看看时间是否能减少。
do{
curChar = (char)getchar();
if(curChar =='\n'){
break;
}
/*
检查当前字符是否和前一个字符相关,如果相关,需要等待w毫秒。
相关的条件:1.当前字符属于 A-Z,2.前一个字符属于A-Z;3.两个字符的lookuptable一样;
*/
if( 'A'<=curChar && curChar<='Z'){
curCharFlag = '1';
} else{
curCharFlag = '0';
}
if (curCharFlag == '1' && //curChar属于A-Z
preCharFlag == '1' && //preChar属于A-Z
(LookupTable[curChar-'A']==LookupTable[preChar-'A'])//两个字符相关
){
result+=w;
}
if (curCharFlag == '1'){
pressTimes = inputCountTable[curChar-'A'];
}else{
pressTimes = 1;
}
result +=p*pressTimes; //输入一个字符需要多个P毫秒;
preChar = curChar;
preCharFlag = curCharFlag;
pressTimes = 0;
}while(1);
printf("%d\n",result);
}
return 0;
}
//Version 2,使用gets直接输入一行,貌似没有通过减少IO次数,提高运行效率
#include <iostream>
#include <stdlib.h>
#include <string.h>
int No_2895();
int getResult(int p,int w);
int main(int argc, char** argv) {
No_2895();
return 0;
}
/*
处理一行字符串,其中只包含空格和英文大写字母。返回处理这行字符串需要的时间。
*/
int getResult(int p,int w){
char LookupTable[26]={ //字母相关关系表,例如映射A为0,B为1,通过查表,可以知道A和B 都对应‘2’
'2','2','2', // A,B,C
'3','3','3', // D,E,F
'4','4','4', // G,H,I
'5','5','5', // J,K,L
'6','6','6', // M,N,O
'7','7','7','7',//P,Q,R,S
'8','8','8', //T,U,V
'9','9','9','9' //W,X,Y,Z
};
int inputCountTable[26]={ //按键次数查询表
1,2,3, // A,B,C
1,2,3, // D,E,F
1,2,3, // G,H,I
1,2,3, // J,K,L
1,2,3, // M,N,O
1,2,3,4,// P,Q,R,S
1,2,3, // T,U,V
1,2,3,4,// W,X,Y,Z
};
char preCharFlag = '0'; //FLAG, 标识字符是否属于A到Z; 0表述不属于,1表示属于;
char curCharFlag = '1';
char tempString[1000]; //题目说明,字符串最大1000个字符。
/////////////////// 从这里开始了! ///////////////////
int result = 0;
//输入一行的例子:1 3 789 B
memset(tempString,0,1000);
if(!gets(tempString)){
return 0;
}
int stringLength = strlen(tempString);
//处理第一个字符:
result += p*inputCountTable[tempString[0]-'A'];
preCharFlag = '1'; //因为题设说明开头没有空白,所以肯定是大写字母,这里的flag是‘1’
//从第二个字符到最后一个字符,依次处理
for(int i = 1;i<stringLength;i++){
if(tempString[i]==' '){ //如果是空格,则 flag 为0;
curCharFlag = '0';
}else{
curCharFlag = '1';
}
//判断当前字符和前一个字符的相关性:
if (curCharFlag == '1' && //curChar属于A-Z
preCharFlag == '1' && //preChar属于A-Z
(LookupTable[tempString[i]-'A']==LookupTable[tempString[i-1]-'A'])//两个字符相关
){
result+=w;
}
if (curCharFlag == '1'){ //如果字符是A-Z,计算时间时需要考虑按了几次;
result += p * inputCountTable[tempString[i]-'A'];
}else{
result += p;
}
preCharFlag = curCharFlag;
}
return result;
}
int No_2895(){
int testCaseNumber;
int p,w;
int result;
scanf("%d",&testCaseNumber);
while(testCaseNumber--){
scanf("%d %d\n",&p,&w);
result = getResult(p,w);
printf("%d\n",result);
}
return 0;
}
/*
使用gets不用scanf的原因是,scanf在出入带有空格的字符串时需要自己考虑比较多的情况,使用麻烦。
*/