程序设计实习MOOC / 程序设计与算法(三)测验和作业题汇总(2022寒假)
( 仅作参考,过OJ但可能有错误 )
001:简单的swap
#include
using namespace std;
class A
{
public:
int x;
int getX() { return x; }
};
void swap(
A &a, A &b //类对象的引用
)
{
int tmp = a.x;
a.x = b.x;
b.x = tmp;
}
int main()
{
A a,b;
a.x = 3;
b.x = 5;
swap(a,b);
cout << a.getX() << "," << b.getX();
return 0;
}
002:难一点的swap
#include
using namespace std;
void swap(
int* &a, int* &b //指针的引用
)
{
int * tmp = a;
a = b;
b = tmp;
}
int main()
{
int a = 3,b = 5;
int * pa = & a;
int * pb = & b;
swap(pa,pb); //交换的是指针的指向,并不是交换的a,b
cout << *pa << "," << * pb;
return 0;
}
003:好怪异的返回值
#include
using namespace std;
// 在此处补充你的代码
int& //返回引用,可以作为左值
getElement(int * a, int i)
{
return a[i];
}
int main()
{
int a[] = {1,2,3};
getElement(a,1) = 10; //函数的返回值为左值,返回值类型为引用
cout << a[1] ;
return 0;
}
004:神秘的数组初始化
//004:神秘的数组初始化
#include
using namespace std;
int main()
{
int * a[] = { //指针数组
// 在此处补充你的代码
NULL, NULL, new int[1], new int[6]
};
*a[2] = 123; //指针a[2] 分配空间,其实一个空间就够了 new int[1]
a[3][5] = 456; //指针a[3] 分配空间,下标为5,空间最少要6
if(! a[0] ) { //指针a[0]为空
cout << * a[2] << "," << a[3][5];
}
return 0;
}
005:编程填空:学生信息处理程序
//005:编程填空:学生信息处理程序
/*
实现一个学生信息处理程序,计算一个学生的四年平均成绩。
要求实现一个代表学生的类,并且类中所有成员变量都是【私有的】。
补充下列程序中的 Student 类以实现上述功能。
输入:
Tom Hanks,18,7817,80,80,90,70
输入数据为一行,包括:
姓名,年龄,学号,第一学年平均成绩,第二学年平均成绩,第三学年平均成绩,第四学年平均成绩。
其中姓名为由字母和空格组成的字符串(输入保证姓名不超过20个字符,并且空格不会出现在字符串两端),
年龄、学号和学年平均成绩均为非负整数。信息之间用逗号隔开。
输出:
Tom Hanks,18,7817,80
输出一行数据,包括:
姓名,年龄,学号,四年平均成绩。
信息之间用逗号隔开
*/
#include
#include
#include
#include
#include
#include
using namespace std;
class Student
{
// 在此处补充你的代码
char name[20]; //scanf("%[^','']",name);
int age; //非负整数 年龄
int id; //非负整数 学号
int s_ave4[4]; //非负整数 1-4学年平均成绩
double ave; // 4年的平均成绩
public:
void input()
{
char comma; //接收逗号
scanf("%[^','']",name);
cin >> comma >> age >> comma >> id;
for(int i=0; i<4; i++)
cin >> comma >> s_ave4[i];
}
void calculate()
{
double sum = 0.0;
for(int i=0; i<4; ++i)
sum += s_ave4[i];
ave = sum / 4.0;
}
void output()
{
cout << name << "," << age << "," << id << "," << ave << endl;
}
};
int main()
{
Student student; // 定义类的对象
student.input(); // 输入数据
student.calculate(); // 计算平均成绩
student.output(); // 输出数据
}
006:奇怪的类复制
#include
using namespace std;
class Sample
{
public:
int v;
// 在此处补充你的代码
public:
Sample():v(0) {} //无参构造
Sample(int v):v(v) {} //有参构造
Sample( const Sample&s ) //拷贝构造
{
v = s.v + 2; // +2
}
};
void PrintAndDouble(Sample o)
{
cout << o.v;
cout << endl;
}
int main()
{
Sample a(5);
Sample b = a; //调用拷贝构造+2 修改对象b
PrintAndDouble(b); //调用拷贝构造+2 修改对象b 输出9
Sample c = 20;
PrintAndDouble(c); //调用拷贝构造+2 修改对象c 输出22
Sample d;
d = a; //调用拷贝构造 +2 修改对象d
cout << d.v;
return 0;
}
007:返回什么才好呢
#include
using namespace std;
class A {
public:
int val;
A(int val):val(val){} //有参
A():val(123){} //无参
A& GetObj(){ //返回对象引用 左值
return *this;
}
};
int main()
{
int m,n;
A a;
cout << a.val << endl;
while(cin >> m >> n) {
a.GetObj() = m; //左值
cout << a.val << endl;
a.GetObj() = A(n); //左值
cout << a.val<< endl;
}
return 0;
}
008:超简单的复数类
#include
#include
#include
using namespace std;
class Complex {
private:
double r,i;
public:
void Print() {
cout << r << "+" << i << "i" << endl;
}
// 在此处补充你的代码
Complex():r( 0.0 ), i( 0.0 ) {} //无参
Complex( const char* str ):r( atoi(str) ), i( atoi(str+2) ) {} //有参 const char*
};
int main() {
Complex a;
a = "3+4i"; a.Print();
a = "5+6i"; a.Print();
return 0;
}
009:哪来的输出
#include
using namespace std;
class A {
public:
int i;
A(int x) { i = x; }
// 在此处补充你的代码
~A(){ cout << i << endl; }
};
int main()
{
A a(1);
A * pa = new A(2);
delete pa;
return 0;
}
011:Big & Base 封闭类问题
#include
#include
using namespace std;
class Base {
public:
int k;
Base(int n):k(n) { }
};
class Big
{
public:
int v;
Base b; //类对象 类组合
// 在此处补充你的代码
Big(int n):v(n),b(n) { }
};
int main()
{
int n;
while(cin >>n) {
Big a1(n);
Big a2 = a1;
cout << a1.v << "," << a1.b.k << endl;
cout << a2.v << "," << a2.b.k << endl;
}
}
012:这个指针哪来的
#include
using namespace std;
struct A
{
int v;
A(int vv):v(vv) { }
// 在此处补充你的代码
const A* getPointer()const { return this;} //指针是const 函数是const
};
int main()
{
const A a(10);
const A * p = a.getPointer();
cout << p->v << endl;
return 0;
}
013:魔兽世界之一:备战
#include
#include
#include
#include
#include
014:MyString ( 注: 要重写拷贝构造函数(深拷贝) )
#include
#include
#include
using namespace std;
class MyString
{
char * p;
public:
MyString(const char * s)
{
if (s)
{
p = new char[strlen(s) + 1];
strcpy(p, s);
}
else
p = NULL;
}
~MyString()
{
if (p)
delete[] p;
}
MyString(const MyString& ms) //拷贝构造( 深拷贝 )
{
//再赋值
if(ms.p) //p不空
{
p = new char[strlen(ms.p) + 1]; //申请空间
strcpy(p, ms.p); //copy内容
}
else
{
p = NULL;
}
}
void Copy(const char *s) //Copy成员函数
{
//先清理空间
if (p) //如果对象成员p不空
{
delete[] p; //释放空间
p = NULL; //置空
}
//再赋值
if(s) //s不空
{
p = new char[strlen(s) + 1]; //申请空间
strcpy(p, s); //copy内容
}
}
friend ostream & operator<<(ostream & os, const MyString & ms) //重载<<运算符( 输出对象)
{
os << ms.p;
return os;
}
MyString & operator =(const MyString &s) // =运算符重载 (对象赋值)
{
if (this == &s) //指针指向参数对象 是同一对象
return *this; //返回对象
//先清理空间
if (p)
{
delete[] p; //释放空间
p = NULL; //置空
}
//再赋值
if (s.p)
{
p = new char[strlen(s.p) + 1]; //申请空间
strcpy(p, s.p); //copy内容
}
return *this;
}
};
int main()
{
char w1[200], w2[100];
while (cin >> w1 >> w2)
{
MyString s1(w1), s2 = s1; //有参构造 拷贝构造( 重写 )
MyString s3(NULL); //有参构造
s3.Copy(w1); //Copy成员函数
cout << s1 << "," << s2 << "," << s3 << endl; //输出对象
s2 = w2; //有参构造( 类型转换 ) 重载=运算符
s3 = s2; //重载=运算符
s1 = s3; //重载=运算符
cout << s1 << "," << s2 << "," << s3 << endl;
}
}
015:看上去好坑的运算符重载
/*
在 C++ 中,类型的名字(包括类的名字)本身也是一种运算符,即类型强制转换运算符。
类型强制转换运算符是单目运算符,也可以被重载,但只能重载为成员函数,不能重载为全局函数。
经过适当重载后,(类型名)对象,这个对对象进行强制类型转换的表达式就等价于
对象.operator 类型名(),即变成对运算符函数的调用。
输入
多组数据,每组一行,整数n
20
30
输出
对每组数据,输出一行,包括两个整数, n-5和n - 8
*/
#include
using namespace std;
class MyInt
{
int nVal;
public:
MyInt( int n)
{
nVal = n ;
}
// 在此处补充你的代码
friend ostream& operator << (ostream& o, MyInt& mi)
{
o << mi.nVal;
return o;
}
MyInt& operator - ( int i)
{
nVal -= i;
return *this;
}
operator int() //类型强制转换运算符 int 重载
{
return nVal;
}
};
int Inc(int n)
{
return n + 1;
}
int main ()
{
int n;
while(cin >>n)
{
MyInt objInt(n);
objInt-2-1-3;
cout << Inc(objInt);
cout <<",";
objInt-2-1;
cout << Inc(objInt) << endl;
}
return 0;
}
016:惊呆!Point竟然能这样输入输出
/*
输入
2 3
4 5
输出
2,3
4,5
*/
#include
using namespace std;
class Point {
private:
int x;
int y;
public:
Point() { };
// 在此处补充你的代码
friend istream& operator >> (istream& i, Point &p){ //p要输入不能是const
i >> p.x >> p.y;
return i;
}
friend ostream& operator << (ostream& o,const Point &p){
o << p.x << "," << p.y; //C++ Primer一书 也建议函数不输出 endl
return o;
}
};
int main()
{
Point p;
while(cin >> p) {
cout << p << endl;
}
return 0;
}
017:二维数组类
#include
#include
using namespace std;
class Array2
{
int** ptr; //二维指针,指向一维指针数组
int x, y; //二维数组下标
public:
Array2() :ptr(NULL),x(0),y(0) {} //无参构造
Array2(int x, int y):x(x),y(y) //有参构造
{
ptr = new int *[x]; //分配指针数组空间
for (int i = 0; i < x; i++)
{
ptr[i] = new int[y]; // 分配指针数组里的指针指向的空间
}
}
int* operator[](int n) //重载[]运算符 返回类型 int*
{
return ptr[n];
}
int operator()(int x, int y) //重载()运算符 a(i,j) 函数对象
{
return ptr[x][y];
}
Array2& operator=(const Array2& a) //重载=运算符 b = a;
{
if (ptr != NULL)
{
for (int i = 0; i < x; i++)
{
delete[]ptr[i]; //释放指针数组里指针指向的空间
}
delete []ptr; //释放指针数组空间
}
ptr = new int*[a.x];
for (int i = 0; i < a.x; i++)
{
ptr[i] = new int[a.y]; //分配二维空间--指针数组的指针指向的空间
memcpy(ptr[i], a.ptr[i], sizeof(int)*a.y); //复制内容
}
x = a.x;
y = a.y;
return *this;
}
~Array2() // 析构
{
if (ptr != NULL)
{
for (int i = 0; i < x; i++)
{
delete[]ptr[i]; //释放指针数组指向的空间
}
delete []ptr; //释放指针数组空间
}
}
};
int main()
{
Array2 a(3,4);//有参构造
int i,j;
for( i = 0; i < 3; ++i )
for( j = 0; j < 4; j ++ )
a[i][j] = i * 4 + j; // a[i] 重载成 ptr[i] --- int*---[j] int*指向的空间赋值
for( i = 0; i < 3; ++i )
{
for( j = 0; j < 4; j ++ )
{
cout << a(i,j) << ","; //函数对象 即重载了()运算符的对象
}
cout << endl;
}
cout << "next" << endl;
Array2 b; //无参构造
b = a; //Array2& operator=(const Array2& a) //重载=运算符
for( i = 0; i < 3; ++i )
{
for( j = 0; j < 4; j ++ )
{
cout << b[i][j] << ","; // b[i] 重载成 ptr[i] 为 int*
}
cout << endl;
}
return 0;
}
018:别叫,这个大整数已经很简化了!
#include
#include
#include
#include
using namespace std;
const int MAX = 110;
class CHugeInt
{
private:
int *a;
int index; //下标
public:
//无参构造函数
CHugeInt()
{
a = new int[MAX]; //分配空间
memset(a, 0, sizeof(int) * MAX); //a置0
index = 1; //下标置1
}
//复制构造函数
CHugeInt(const CHugeInt& x)
{
index = x.index;
a = new int[MAX];
memset(a, 0, sizeof(int) * MAX);
//拷贝a
for(int i = 1; i <= index; i++)
{
a[i] = x.a[i];
}
}
//析构函数
~CHugeInt()
{
if(a)
{
delete [] a;
a = NULL;
}
}
//int参数构造函数
CHugeInt(int n)
{
a = new int[MAX];
memset(a, 0, sizeof(int) * MAX);//a值0
index = !n ? 1 : 0;//参数n为0,下标值1 ,否则值0
while(n)
{
a[++index] = n % 10;
n /= 10;
}
}
//参数为char *构造函数
CHugeInt(const char *c)
{
a = new int[MAX];
memset(a, 0, sizeof(int) * MAX);
index = strlen(c);
for(int i = index - 1; i >= 0; i--)
a[index - i] = c[i] - '0';
}
//重载[]运算符
int& operator[](int x)
{
return a[x];
}
//两对象赋值,重载=运算符,成员函数
CHugeInt& operator =(const CHugeInt& x)
{
if( this == &x )
{
return *this;
}
if(a)
{
delete[] a;
a = NULL;
}
if(x.a)
{
a = new int[MAX];
memset(a,0,sizeof(*a));
index = x.index;
for(int i = 1; i <= index; i++)
a[i] = x.a[i];
}
return *this;
}
//两对象相加,重载=运算符,友元函数
friend CHugeInt operator +(CHugeInt a, CHugeInt b)
{
CHugeInt c;
c.index = max(a.index, b.index);
for(int i = 1; i <= c.index; i++)
c[i] = a[i] + b[i]; //重载[]运算符
for(int i = 1; i <= c.index; i++)//处理进位
{
if(c[i] >= 10)
{
if(i == c.index) //扩充
{
c.index++;
}
c[i + 1] += c[i] / 10; //进位
c[i] %= 10; //取余
}
}
return c;
}
//CHugeInt类对象输出
friend ostream& operator << (ostream& os, const CHugeInt& x)
{
for(int i = x.index; i >= 1; i--) //逐位输出
os << x.a[i];
return os;
}
// int 与对象相加
friend CHugeInt operator +(int a, const CHugeInt& b)
{
return CHugeInt(a) + b;//两个CHugeInt类对象相加
}
//+=
CHugeInt& operator +=(int x)
{
*this = *this + CHugeInt(x);
return *this;
}
//前置++
CHugeInt& operator ++()
{
*this = *this + CHugeInt(1);
return *this;
}
//后置++
CHugeInt operator ++(int)
{
CHugeInt tmp = *this;
*this = CHugeInt(1) + *this;
return tmp;
}
};
int main()
{
char s[210];
int n;
while (cin >> s >> n)
{
CHugeInt a(s); //const char*
CHugeInt b(n); //int n
//friend ostream& operator << (ostream& os, const CHugeInt& x)
//friend CHugeInt operator +(CHugeInt a, CHugeInt b)
cout << a + b << endl;
//friend CHugeInt operator +(int a, const CHugeInt& b)
cout << n + a << endl;
//调用参数为int的构造函数,n会类型转换为对象
cout << a + n << endl;
//CHugeInt& operator +=(int x)
b += n;
//CHugeInt& operator ++()
cout << ++ b << endl;
//CHugeInt operator ++(int)
cout << b++ << endl;
cout << b << endl;
}
return 0;
}
019:全面的MyString
#include
#include
using namespace std;
int strlen(const char * s)
{
int i = 0;
for(; s[i]; ++i);
return i;
}
void strcpy(char * d,const char * s)
{
int i = 0;
for( i = 0; s[i]; ++i)
d[i] = s[i];
d[i] = 0;
}
int strcmp(const char * s1,const char * s2)
{
for(int i = 0; s1[i] && s2[i] ; ++i)
{
if( s1[i] < s2[i] )
return -1;
else if( s1[i] > s2[i])
return 1;
}
return 0;
}
void strcat(char * d,const char * s)
{
int len = strlen(d);
strcpy(d+len,s);
}
class MyString
{
char *p;
public:
//1、 构造函数----创建对象
MyString()//无参构造函数--
{
p = NULL;
};
MyString(const char *s)//有参构造函数--char *
{
p = new char[strlen(s)+ 1];
strcpy(p,s);
}
MyString(const MyString & x) //拷贝构造--深拷贝
{
if(x.p)
{
p = new char[strlen(x.p)+1];
strcpy(p,x.p);
}
else
p = NULL;
}
//2、 析构----释放空间
~MyString()
{
if(p)delete []p;
}
//3、友元函数----输出对象
friend ostream& operator << (ostream& os, const MyString &s)
{
if(s.p)os << s.p;
return os;
}
//4.重载=运算符----对象向对象赋值
MyString & operator=(const MyString & x)
{
if(p == x.p)
return *this;
if(p)
delete[] p;
if(x.p)
{
p = new char[strlen(x.p)+1];
strcpy(p,x.p);
}
else
p = NULL;
return *this;
}
//5.重载[] 返回引用 可以修改字符
char & operator[](int x)
{
return p[x];
}
//6.对象 + 对象
MyString operator+(const MyString &ms)
{
MyString temp;
temp.p = new char[strlen(p) + strlen(ms.p)+1];
strcpy(temp.p, p);
strcat(temp.p, ms.p);
return temp;
}
//7.对象 += 字符串 ----字符串先转对象--构造
MyString& operator +=(const char *s)
{
*this = *this + MyString(s); //修改了字符串
return *this;
}
//8.字符串 + 对象 ----字符串先转对象--构造
//对象 + 字符串,字符串会强转为对象
friend MyString operator+(const char*str, const MyString &ms)
{
return MyString(str) + ms;
}
//9.重载<类对象比较
bool operator <(const MyString &s)
{
return strcmp(p,s.p)==-1;
}
//10.重载> 类对象比较
bool operator >(const MyString &s)
{
return strcmp(p,s.p)==1;
}
//11.重载== 类对象比较
bool operator ==(const MyString &s)
{
return strcmp(p,s.p)==0;
}
//12.()运算符重载 substr
char* operator()(int start,int len) //第二个参数是复制的长度
{
char* temp = new char[len];
int index = 0;
while( index < len ){
temp[index++] = p[start++];
}
temp[index] = '\0';
return temp;
}
};
int CompareString( const void * e1, const void * e2)
{
MyString * s1 = (MyString * ) e1;
MyString * s2 = (MyString * ) e2;
if( * s1 < *s2 )
return -1;
else if( *s1 == *s2)
return 0;
else if( *s1 > *s2 )
return 1;
}
int main()
{
MyString s1("abcd-"),s2,s3("efgh-"),s4(s1); //有参构造、 无参构造、 拷贝构造
MyString SArray[4] = {"big","me","about","take"};
cout << "1. " << s1 << s2 << s3<< s4<< endl; //重载 << 运算符
s4 = s3; // 重载 = 运算符
s3 = s1 + s3; // 重载 + 运算符--- 成员函数---两对象相加
cout << "2. " << s1 << endl;
cout << "3. " << s2 << endl;
cout << "4. " << s3 << endl;
cout << "5. " << s4 << endl;
cout << "6. " << s1[2] << endl; //重载 [] 运算符
s2 = s1;
s1 = "ijkl-"; //字符串默认强转--调用构造函数
s1[2] = 'A' ;
cout << "7. " << s2 << endl;
cout << "8. " << s1 << endl;
s1 += "mnop";
cout << "9. " << s1 << endl;
s4 = "qrst-" + s2;
cout << "10. " << s4 << endl;
s1 = s2 + s4 + " uvw " + "xyz";
cout << "11. " << s1 << endl;
qsort(SArray,4,sizeof(MyString),CompareString);
for( int i = 0; i < 4; i ++ )
cout << SArray[i] << endl;
//s1的从下标0开始长度为4的子串
cout << s1(0,4) << endl;
//s1的从下标5开始长度为10的子串
cout << s1(5,10) << endl;
return 0;
}
020:继承自string的MyString
#include
#include
#include
#include
using namespace std;
class MyString:public string
{
public:
MyString():string(){ }; //无参构造
MyString(const char* str):string(str){ }; //有参构造,const char* 强转 或者 叫类型转换
MyString(const string& str):string(str){};//有参构造,对象强转 或者 叫类型转换
MyString operator () (int i, int j) //函数对象用到继承自string的substr函数
{
return substr(i, j); //子串 返回的是string
}
};
int main()
{
MyString s1("abcd-"),s2,s3("efgh-"),s4(s1);
MyString SArray[4] = {"big","me","about","take"};
cout << "1. " << s1 << s2 << s3<< s4<< endl;
s4 = s3;
s3 = s1 + s3;
cout << "2. " << s1 << endl;
cout << "3. " << s2 << endl;
cout << "4. " << s3 << endl;
cout << "5. " << s4 << endl;
cout << "6. " << s1[2] << endl;
s2 = s1;
s1 = "ijkl-";
s1[2] = 'A' ;
cout << "7. " << s2 << endl;
cout << "8. " << s1 << endl;
s1 += "mnop";
cout << "9. " << s1 << endl;
s4 = "qrst-" + s2;
cout << "10. " << s4 << endl;
s1 = s2 + s4 + " uvw " + "xyz";
cout << "11. " << s1 << endl;
sort(SArray,SArray+4);
for( int i = 0;i < 4;i ++ )
cout << SArray[i] << endl;
//s1的从下标0开始长度为4的子串
cout << s1(0,4) << endl;
//s1的从下标5开始长度为10的子串
cout << s1(5,10) << endl;
return 0;
}
021:魔兽世界之二:装备
#include
#include
#include
#include
#include
022:看上去像多态
#include
using namespace std;
class B
{
private:
int nBVal;
public:
void Print()
{
cout << "nBVal="<< nBVal << endl;
}
void Fun()
{
cout << "B::Fun" << endl;
}
B ( int n )
{
nBVal = n;
}
};
// 在此处补充你的代码
class D:public B
{
int nDVal;
public:
D(int n): B(n*3), nDVal(n)
{
}
void Fun()
{
cout << "D::Fun" << endl;
}
void Print()
{
B::Print();
cout << "nDVal=" << nDVal << endl;
}
};
int main()
{
B * pb;
D * pd;
D d(4); //D构造 值4,B值4*3=12
d.Fun(); //D::Fun
pb = new B(2); //B构造 值2
pd = new D(8); //D构造 值8,B值8*3=24
pb -> Fun(); //B::Fun
pd->Fun(); //D::Fun
pb->Print (); //nBVal=2
pd->Print (); //nBVal=24 //nDVal=8 //打印B、D值
pb = & d;
pb->Fun(); //B::Fun
pb->Print(); //nBVal=12 //打印B值//调用B类Print()函数
return 0;
}
023:Fun和Do
#include
using namespace std;
class A
{
private:
int nVal;
public:
void Fun()
{
cout << "A::Fun" << endl;
};
void Do()
{
cout << "A::Do" << endl;
}
};
class B:public A
{
public:
virtual void Do()
{
cout << "B::Do" << endl;
}
};
class C:public B
{
public:
void Do( )
{
cout <<"C::Do"<
024:这是什么鬼delete
#include
using namespace std;
class A
{
public:
A() { }
//通过基类的指针来删除派生类的对象时,基类的析构函数应该是虚的
virtual~A(){ cout << "destructor A" << endl; }
};
class B:public A {
public:
~B() { cout << "destructor B" << endl; }
};
int main()
{
A * pa;
pa = new B;
delete pa;
return 0;
}
025:怎么又是Fun和Do
#include
using namespace std;
class A {
private:
int nVal;
public:
void Fun()
{ cout << "A::Fun" << endl; };
virtual void Do()
{ cout << "A::Do" << endl; }
};
class B:public A {
public:
virtual void Do()
{ cout << "B::Do" << endl;}
};
class C:public B {
public:
void Do( )
{ cout <<"C::Do"<Fun(); p->Do();
}
int main() {
Call( new A());
Call( new C());
return 0;
}
026:编程填空:统计动物数量
#include
using namespace std;
// 在此处补充你的代码
class Animal
{
public:
static int number;
virtual ~Animal() { } //基类虚析构
};
int Animal::number = 0;
class Dog:public Animal
{
public:
static int number;
Dog()
{
number++;
Animal::number++;
}
~Dog()
{
number--;
Animal::number--;
}
};
int Dog::number = 0;
class Cat:public Animal
{
public:
static int number;
Cat()
{
number++;
Animal::number++;
}
~Cat()
{
number--;
Animal::number--;
}
};
int Cat::number = 0;
void print()
{
cout << Animal::number << " animals in the zoo, "
<< Dog::number << " of them are dogs, "
<< Cat::number << " of them are cats" << endl;
}
int main()
{
print();
Dog d1, d2;
Cat c1;
print();
Dog* d3 = new Dog();
Animal* c2 = new Cat;
Cat* c3 = new Cat;
print();
delete c3;
delete c2;
delete d3;
print();
}
027:简单的SumArray
#include
#include
using namespace std;
template
T SumArray( T* begin, T* end )
{
T temp = *begin++;
for(T* i=begin; i
028:简单的foreach
#include
#include
using namespace std;
template // 2个类型
void MyForeach(T* start, T* end, void (*function)( T1 ))
{
for(T* p=start; p> m >> n)
{
for(int i = 0; i < m; ++i)
cin >> array[i];
for(int j = 0; j < n; ++j)
cin >> a[j];
MyForeach(array,array+m,Print);
cout << endl;
MyForeach(a,a+n,Inc);
for(int i = 0; i < n; ++i)
cout << a[i] << ",";
cout << endl;
}
return 0;
}
029:简单的Filter
#include
#include
using namespace std;
// 在此处补充你的代码
template
T* Filter( T* start, T* end, T* start1, bool(*function)( T ) )
{
while( start 2;
}
bool LongerThan3(string s)//长度大于3的string
{
return s.length() > 3;
}
string as1[5] = {"Tom","Mike","Jack","Ted","Lucy"};
string as2[5];
int a1[5] = { 1,2,3,4,5};
int a2[5];
int main()
{
string * p = Filter(as1,as1+5,as2,LongerThan3);
for(int i = 0; i < p - as2; ++i)
cout << as2[i];
cout << endl;
int * p2 = Filter(a1,a1+5,a2,LargerThan2);
for(int i = 0; i < p2-a2; ++i)
cout << a2[i] << ",";
return 0;
}
030:你真的搞清楚为啥 while(cin >> n) 能成立了吗?
#include
using namespace std;
class MyCin
{
bool flag;
public:
MyCin():flag(true){ }
MyCin& operator >> (int& n)
{
std::cin >> n;
if( n == -1 ) //输入值为-1 MyCin对象为false
{
flag = false;
}
return *this;
}
operator bool() //bool运算符重载 判断MyCin对象的true或false
{
return flag;
}
};
int main()
{
MyCin m;
int n1,n2;
while( m >> n1 >> n2)
cout << n1 << " " << n2 << endl;
return 0;
}
031:山寨版istream_iterator
#include
#include
using namespace std;
template
class CMyistream_iterator
{
private:
istream& ist;
T now; //类型 T
public:
CMyistream_iterator(){}
CMyistream_iterator(istream &ist):ist(ist)//构造函数ist为cin的引用
{ //同时输入now的值
ist >> now;
}
T operator*(){ //重载*运算符,返回 now
return now;
}
void operator ++(int){ //重载++运算符 再次输入覆盖now
ist >> now;
}
};
int main()
{
int t;
cin >> t;
while( t -- ) {
CMyistream_iterator inputInt(cin);
int n1,n2,n3;
n1 = * inputInt; //读入 n1
int tmp = * inputInt;
cout << tmp << endl;
inputInt ++;
n2 = * inputInt; //读入 n2
inputInt ++;
n3 = * inputInt; //读入 n3
cout << n1 << " " << n2<< " " << n3 << " ";
CMyistream_iterator inputStr(cin);
string s1,s2;
s1 = * inputStr;
inputStr ++;
s2 = * inputStr;
cout << s1 << " " << s2 << endl;
}
return 0;
}
032:这个模板并不难
#include
#include
#include
using namespace std;
template
class myclass {
// 在此处补充你的代码
int size;
T* p;
public:
myclass( T* arr, const int size ):size(size)
{
p = new T[size]; // !!! 分配空间 T类型
for(int i = 0; i < size; i++) // 赋值
p[i] = arr[i];
}
~myclass( ) {
delete [] p;
}
void Show()
{
for( int i = 0;i < size;i ++ ) {
cout << p[i] << ",";
}
cout << endl;
}
};
int a[100];
int main() {
char line[100];
while( cin >> line ) {
myclass obj(line,strlen(line));
obj.Show();
int n;
cin >> n;
for(int i = 0;i < n; ++i)
cin >> a[i];
myclass obj2(a,n);
obj2.Show();
}
return 0;
}
033:排序,又见排序!
#include
using namespace std;
bool Greater2(int n1,int n2)
{
return n1 > n2;
}
bool Greater1(int n1,int n2)
{
return n1 < n2;
}
bool Greater3(double d1,double d2)
{
return d1 < d2;
}
template //T1为for循环变量使用,T2为数据类型使用
void mysort(T1 left, T1 right, bool (*cmp)(T2,T2))
{
for(T1 i = left; i != right; i++) //冒泡排序 T1为指针类型
{
for(T1 j = i + 1; j != right; j++)
{
if( cmp(*j, *i) ) // < *j排在前 ( 比较函数 )
{
swap(*j, *i); // *i *j 在前在后一样
}
}
}
}
#define NUM 5
int main()
{
int an[NUM] = { 8,123,11,10,4 };
mysort(an,an+NUM,Greater1); //从小到大排序
for( int i = 0;i < NUM; i ++ )
cout << an[i] << ",";
mysort(an,an+NUM,Greater2); //从大到小排序
cout << endl;
for( int i = 0;i < NUM; i ++ )
cout << an[i] << ",";
cout << endl;
double d[6] = { 1.4,1.8,3.2,1.2,3.1,2.1};
mysort(d+1,d+5,Greater3); //将数组从下标1到下标4从小到大排序
for( int i = 0;i < 6; i ++ )
cout << d[i] << ",";
return 0;
}
034:goodcopy
#include
using namespace std;
template
struct GoodCopy
{
private:
T * ptr; //借用空间
public:
void operator()(T * start,T * end,T * start2)
{
int len = end - start;
ptr = new T[len + 1];
for(int i = 0;i
void Print(T s,T e)
{
for(; s != e; ++s)
cout << * s << ",";
cout << endl;
}
int main()
{
int t;
cin >> t;
while( t -- )
{
int m ;
cin >> m;
for(int i = 0; i < m; ++i)
cin >> a[i];
GoodCopy()(a,a+m,b);
Print(b,b+m);
//a,a+m --> a+m/2会覆盖a数组a+m/2之后的部分
//所以要借用其他空间保存a数组
//然后再从其他空间复制回来
GoodCopy()(a,a+m,a+m/2);//函数对象( 临时对象 )
Print( a+m/2, a+m/2+m );
for(int i = 0; i < m; ++i)
cin >> c[i];
GoodCopy()(c,c+m,d);
Print(c,c+m);
//同理
GoodCopy()(c,c+m,c+m/2);
Print( c+m/2, c+m/2+m );
}
return 0;
}
035:按距离排序
#include
#include
#include
#include
using namespace std;
template
struct Closer
{
private:
T1 val;//输入的值,题目是int型,string型的值
T2 op; //函数指针,题目是Distance1,Distance2
public:
Closer( const T1& val, T2 op ):val(val),op(op) { }
bool operator()( const T1& x, const T1& y )
{
//1输入的数字与a数组的每个元素之差的绝对值小的在前面
if (op(val, x) < op(val, y)//2输入的字符串长度与b数组的每个元素的长度之差的绝对值小的在前面
|| (op(val, x) == op(val, y)) && x < y) //1差的绝对值相等的,值小的排在前面 比如2与3,2与1之差的绝对值是相等的
return true; //2如果长度相等,字典序小的排在前面
return false;
}
};
int Distance1(int n1,int n2)
{
return abs(n1-n2);
}
int Distance2(const string & s1, const string & s2)
{
//输入的字符串长度与b数组的每一个元素的长度的差的绝对值小的在前面
return abs((int)s1.length()- (int) s2.length());
}
//对数组a按和n的距离从小到大排序后输出。距离相同的,值小的排在前面。
int a[10] = { 0,3,1,4,7,9,20,8,10,15};
//然后对数组b,按照和s的距离从小到大输出。距离相同的,字典序小的排在前面
string b[6] = {"American","Jack","To","Peking","abcdefghijklmnop","123456789"};
int main()
{
int n;
string s;
while( cin >> n >> s )
{
sort( a,a+10,Closer (n,Distance1) ); //对象传进去后会调用()运算符重载
//Closer (n,Distance1) 模板类的函数对象 调用的构造函数
for(int i = 0; i < 10; ++i)
cout << a[i] << "," ;
cout << endl;
sort( b,b+6,Closer (s,Distance2) );
for(int i = 0; i < 6; ++i)
cout << b[i] << "," ;
cout << endl;
}
return 0;
}
036:很难蒙混过关的CArray3d三维数组模板类
#include
#include
#include
using namespace std;
template
class CArray3D
{ // 一维的是一条线, 线一行一行的弯曲折叠就成了二维的面
// 一个一个的面折叠起来就是三维的立体
class CArray2D
{
private:
int row; // 行
int col; // 列
T *ptr; //一维指针
public:
CArray2D() :row(0), col(0)
{
ptr = new T[1];
}
void init(int row, int col)
{
this->row = row;
this->col = col;
delete[]ptr;
ptr = new T[ row * col + 1];
}
T * operator[](int i) //二维中,每行的首地址
{
return (ptr + i * col);//每行的首地址
}
operator T*() //重载T类型指针 T* ( 二维对象强转一维指针 )
{
return ptr;
}
};
CArray2D * a; //二维指针
public:
CArray3D(int level,int row,int col)
{
a = new CArray2D[level];
for (int i = 0; i < level; ++i)
a[i].init(row, col); //a[i] 二维对象
}
CArray2D& operator[](int i) //返回值为引用,左值
{
return a[i]; //二维对象
}
};
//[]运算符,三维返回的是二维的对象引用,二维返回的是一维的指针,一维返回的是地址中的值
CArray3D a(3,4,5);
CArray3D b(3,2,2);
void PrintA()
{
for(int i = 0; i < 3; ++i)
{
cout << "layer " << i << ":" << endl;
for(int j = 0; j < 4; ++j)
{
for(int k = 0; k < 5; ++k)
cout << a[i][j][k] << "," ;
cout << endl;
}
}
}
void PrintB()
{
for(int i = 0; i < 3; ++i)
{
cout << "layer " << i << ":" << endl;
for(int j = 0; j < 2; ++j)
{
for(int k = 0; k < 2; ++k)
cout << b[i][j][k] << "," ;
cout << endl;
}
}
}
int main()
{
int No = 0;
for( int i = 0; i < 3; ++ i )
{
a[i]; // 层 -- 每层都是2维 (二维的对象)
for( int j = 0; j < 4; ++j )
{
a[j][i];// 行
for( int k = 0; k < 5; ++k )
a[i][j][k] = No ++; // 列
a[j][i][i];
}
}
PrintA();
//第一个参数void* a[1]是二维对象 二维类要重载T类型指针T*
memset(a[1],-1,20*sizeof(int));
memset(a[1],-1,20*sizeof(int));
PrintA();
//二维对象a[1]重载[]为一维指针(ptr + i * col)
//一维[]为指针 (地址) 取值
memset(a[1][1],0,5*sizeof(int)); //a[1][1]
PrintA();
for( int i = 0; i < 3; ++ i )
for( int j = 0; j < 2; ++j )
for( int k = 0; k < 2; ++k )
b[i][j][k] = 10.0/(i+j+k+1);
PrintB();
int n = a[0][1][2]; //第0层第1行第2列的值
double f = b[0][1][1];
cout << "****" << endl;
cout << n << "," << f << endl;
return 0;
}
037:函数对象的过滤器
#include
#include
using namespace std;
//vector元素为对象的,对象要有比较函数
struct A
{
int v;
A() { }
A(int n):v(n) { };
bool operator<(const A & a) const //比较函数
{
return v < a.v;
}
};
template
struct FilterClass
{ // 模板类的函数对象 FilterClass(m,n)
T low;
T high;
FilterClass(int m,int n):low(m),high(n) {}
bool operator()(const T & rhs) //重载了()运算符,对象为函数对象
{
if( low < rhs && rhs < high) //选取在 low 至 high 之间
return true; //不包含 low high
return false;
}
};
template
void Print(T s,T e)
{
for(; s!=e; ++s)
cout << *s << ",";
cout << endl;
}
template
T2 Filter( T1 s,T1 e, T2 s2, T3 op)
{
for(; s != e; ++s)
{
if( op(*s) ) //函数对象,参数是T1类型的*s //bool operator()(const T & rhs)
{ //本题为迭代器取值
* s2 = * s; // 在函数对象的限定范围之内的复制
++s2;
}
}
return s2;
}
ostream & operator <<(ostream & o,A & a)
{
o << a.v;
return o;
}
vector ia;
vector aa;
int main()
{
int m,n;
while(cin >> m >> n)
{
ia.clear();
aa.clear();
int k,tmp;
cin >> k;
for(int i = 0; i < k; ++i)
{
cin >> tmp;
ia.push_back(tmp);
aa.push_back(tmp);
}
vector ib(k);
vector ab(k);
//FilterClass(m,n) 是对象//ia.begin() 是 vector::iterator
vector::iterator p = Filter(ia.begin(),ia.end(),ib.begin(),FilterClass(m,n));
Print(ib.begin(),p); //p --> 返回的迭代器ib.end()
vector::iterator pp = Filter(aa.begin(),aa.end(),ab.begin(),FilterClass(m,n));
Print(ab.begin(),pp);
}
return 0;
}
038:白给的list排序
#include
#include
#include
#include
using namespace std;
int main()
{
double a[] = {1.2,3.4,9.8,7.3,2.6};
list lst(a,a+5);
lst.sort(
greater() //降序
//less() //升序
);
for(list::iterator i = lst.begin(); i != lst.end(); ++i)
cout << * i << "," ;
return 0;
}
/*
/// One of the @link comparison_functors comparison functors@endlink.
template
struct greater : public binary_function<_Tp, _Tp, bool>
{
bool
operator()(const _Tp& __x, const _Tp& __y) const
{
return __x > __y;
}
}; */
/*
/// One of the @link comparison_functors comparison functors@endlink.
template
struct less : public binary_function<_Tp, _Tp, bool>
{
bool
operator()(const _Tp& __x, const _Tp& __y) const
{
return __x < __y;
}
}; */
039:我自己的 ostream_iterator
#include
#include
#include
using namespace std;
//遍历输出
template
void Copy(T1 s,T1 e, T2 x) //output迭代器x++
{ //list迭代器T1
for(; s != e; ++s,++x) //输出
*x = *s; //迭代器对象赋值
}
template
class myostream_iteraotr
{
private:
ostream & os; //cout
string s; //"," 或 "--"
T val; //* 赋值
public:
myostream_iteraotr(ostream & os, const string &s) :os(os), s(s) { }
T & operator*() // * 运算符重载 返回T类型引用T& 左值
{
return val;
}
myostream_iteraotr& operator++() //++ 运算符重载 实现输出
{
os<< val << s; //cout << val << ","
return *this;
}
};
int main()
{ const int SIZE = 5;
int a[SIZE] = {5,21,14,2,3};
double b[SIZE] = { 1.4, 5.56,3.2,98.3,3.3};
list lst(a,a+SIZE);
myostream_iteraotr output(cout,",");
Copy( lst.begin(),lst.end(),output); //output迭代器++ 输出
cout << endl;
myostream_iteraotr output2(cout,"--");
Copy(b,b+SIZE,output2);
return 0;
}
040:List
#include
#include
#include
041:Set
/*
现有一整数集(允许有重复元素),初始为空。
我们定义如下操作:
add x 把x加入集合
del x 把集合中所有与x相等的元素删除
ask x 对集合中元素x的情况询问
对每种操作,我们要求进行如下输出。
add 输出操作后集合中x的个数
del 输出操作前集合中x的个数
ask 先输出0或1表示x是否曾被加入集合(0表示不曾加入),
再输出当前集合中x的个数,中间用空格格开。 */
/*
7
add 1---1 //加入1 有一个1
add 1---2 //再加入1 有二个1
ask 1---1 2 //问是否加入过1 还有几个 2
ask 2---0 0 //问是否加入过2 还有几个 0
del 2---0 //删除几个 2
del 1---2 //删除几个 1
ask 1---1 0 //是否加入过1 还有几个 0
*/
#include
#include
#include
using namespace std;
int main()
{
multiset ms; //允许有重复元素,初始为空
set s; //不允许重复元素 记录曾经加入过
int n, num;
string str;
cin >> n;
while (n--)
{
cin >> str;
if (str == "add")
{
cin >> num;
s.insert(num);
ms.insert(num);
cout << ms.count(num) << endl; //插入集合中元素为x的个数
}
else if (str == "ask")
{
cin >> num;
if ( s.count(num) ) //对集合中元素x的情况询问,是否曾被加入
cout << "1" << " ";
else
cout << "0" << " ";
cout << ms.count(num) << endl; //还有几个
}
else if (str == "del")
{
cin >> num;
cout << ms.count(num) << endl; //删除几个
ms.erase(num); //把集合中所有与x相等的元素删除
}
}
return 0;
}
042:热血格斗场
#include
#include
043:冷血格斗场
#include
#include
044:编程填空:数据库内的学生信息
#include
#include
#include
045:魔兽世界三(开战)
封闭类:
一个类的对象是其他类的对象,这个对象叫成员对象,有成员对象的类叫封闭类,任何生成封闭类对象的语句,都要让编译器明白,对象中的成员对象,是如何初始化的:通过封闭类的构造函数的初始化列表,成员对象初始化列表中的参数可以是任意复杂的表达式,可以包括函数,变量,只要表达式中的函数或变量有定义就行
封闭类对象生成时,先执行所有对象成员的构造函数,然后才执行封闭类的构造函数,对象成员的构造函数调用次序和对象成员在类中的说明次序一致,与它们在成员初始化列表中出现的次序无关
类A拥有类B的代码说明:
#include
using namespace std;
//1、类前置声明 只是让类A知道类B,但不知道类B的成员,比如类B的成员函数print()
//所以类A的成员函数PrintB(),要在类B整体声明之后、类外定义实现
class B;
//类A用到了类B,类B在类A下面声明,需要前置声明类B
//类A整体声明
class A
{
int i;
public:
A(int i):i(i) { }
void PrintB(B *b);
//类A成员函数用到了类B,成员函数要在类B声明之下定义实现
};
//类B整体声明
class B
{
int j;
public:
B(int j):j(j) { }
void print(); //声明了print()
};
//2、在类B声明之后、在类外实现
//这里知道了类B的成员函数print(),因为上面B类声明了print()
void A:: PrintB(B *b)
{
b->print();
}
void B::print()
{
cout << "B = " << j << endl;
}
int main()
{
A a(111);
B b(222);
a.PrintB(&b);
return 0;
}
this指针:
this指针其作用,就是指向成员函数所作用的对象,静态成员函数中不能使用this指针,因为静态成员函数是属于类的,不属于任何对象
#include
using namespace std;
class A{
int i;
public:
void Hello(){ cout << "Hello" << endl; }
// void Hello(A* this) { cout << "Hello" << endl; }
};
int main()
{
A* p = NULL;
p -> Hello(); //输出Hello
// Hello(p);
return 0;
}
#include
using namespace std;
class A{
int i;
public:
void Hello(){ cout << i << "Hello" << endl; }
// void Hello(A* this) { cout << this->i << "Hello" << endl; }
//this->i !! this为NULL,出错
};
int main()
{
A* p = NULL;
p -> Hello();
// Hello(p);
return 0;
}
类A拥有类B、类B拥有类A的代码说明:
#include
using namespace std;
//1、类前置声明 只是让类A知道类B,但不知道类B的成员,比如类B的成员函数print()
//所以类A的成员函数PrintB(),要在类B整体声明之后、类外定义实现
class B;
//类A用到了类B,类B在类A下面声明,需要前置声明类B
//类A整体声明
class A
{
int i;
public:
A(int i):i(i) { }
int getI() { return i; }
void PrintB(B *b); // !!!A中有B
//类A成员函数用到了类B,成员函数要在类B声明之下定义实现
};
//类B整体声明
class B
{
int j;
public:
B(int j):j(j) { }
void print(A* a); //声明了print() //!!!B中有A
};
//2、在类B声明之后、在类外实现
//这里知道了类B的成员函数print(),因为上面B类声明了print()
void A:: PrintB(B *b)
{
b->print(this); //this指针
}
void B::print(A* a)
{
cout << "A = " << a->getI() << endl;
}
int main()
{
A a(111);
B b(222);
a.PrintB(&b);
return 0;
}
第一部分 面向对象的编程
面向对象编程(Object-oriented programming , OOP),基于三个概念:数据抽象、继承 和 动态绑定
动态绑定使编译器能够在运行时决定是使用基类中定义的函数还是派生类中定义的函数,在C++中,通过基类的引用或指针调用虚函数时,发生动态绑定,调用的虚函数在运行时确定,被调用的函数是引用或指针所指向对象的实际类型所定义
在C++中基类必须指出希望派生类重新定义哪些函数,定义为virtual的函数即虚函数,不是基类期待派生类重新定义的,不能定义为虚函数
#include
using namespace std;
class Base{
int base_num;
public:
Base( int number ): base_num(number){}
virtual int getNum(){ //虚函数,期望派生类重定义
return base_num;
}
};
class Derived:public Base
{
int derived_num;
public:
Derived( int num1, int num2 ):Base(num1), derived_num(num2){}
virtual int getNum(){ //重定义的函数
return derived_num;
}
};
void printNum(Base &b){ //基类的引用
cout << b.getNum() << endl;
}
void printNum(const Base &b){ //临时对象是右值,可以用const绑定
cout << "临时对象是右值,可以用const绑定" << endl;
}
/* void printNum(const Base &b){ //基类的引用是const
cout << b.getNum() << endl; //调用了非const的函数不可以
} */
int main()
{
Derived d(80,90);
printNum(d); //传的是派生类的对象
printNum(Derived(50,60)); //临时对象是右值,可以用const绑定
return 0;
}
第二部分 泛型编程
模板机制,以及标准模板库STL
标准模板库(Standard Template Library)就是一些常用数据结构和算法的模板的集合,有了STL,不必再写太多的标准数据结构和算法,并且可以获得非常高的性能
STL六大部件:容器(Containers)、分配器(Allocators)、算法(Alogrithms)、迭代器(Iterators)、仿函数(Functors,头文件为
一、容器(Containers)
容器的定义:
在数据存储上,有一种对象类型,它可以持有其它对象或指向其它对象的指针,这种对象类型就叫做容器。很简单,容器就是保存其它对象的对象,当然这是一个朴素的理解,这种“对象”还包含了一系列处理“其它对象”的方法。容器即物之所在,容器是STL的核心部件之一,是迭代器的依附,是算法作用的目标。
容器的种类:
顺序容器:是一种各元素之间有顺序关系的线性表,是一种线性结构的可序群集。顺序性容器中的每个元素均有固定的位置,除非用删除或插入的操作改变这个位置。顺序容器的元素排列次序与元素值无关,而是由元素添加到容器里的次序决定。顺序容器包括:vector(向量)、list(列表)、deque(队列)。关联容器:关联式容器是非线性的树结构,更准确的说是二叉树结构。各元素之间没有严格的物理上的顺序关系,也就是说元素在容器中并没有保存元素置入容器时的逻辑顺序。但是关联式容器提供了另一种根据元素特点排序的功能,这样迭代器就能根据元素的特点“顺序地”获取元素。元素是有序的集合,默认在插入的时候按升序排列。关联容器包括:map(集合)、set(映射)、multimap(多重集合)、multiset(多重映射)。容器适配器:本质上,适配器是使一种不同的行为类似于另一事物的行为的一种机制。容器适配器让一种已存在的容器类型采用另一种不同的抽象类型的工作方式实现。适配器是容器的接口,它本身不能直接保存元素,它保存元素的机制是调用另一种顺序容器去实现,即可以把适配器看作“它保存一个容器,这个容器再保存所有元素”。STL 中包含三种适配器:栈stack 、队列queue 和优先级队列priority_queue 。
容器类自动申请和释放内存,因此无需new和delete操作。
不同容器的使用方法:
1、set 有序性,键值为对象,要求有比较函数
/*
* 维护平面点
一开始平面上一个点都没有
每次可以插入一个点,删除一个已经存在的点,或者按照x 或y 来查询一个存在的点
保证任何时候任意两个点一定是一个点严格在另一个点的右下方
即两点(x1, y1), (x2, y2),必定有x1 > x2 且y1 < y2 ,或者x1 < x2 且y1 > y2
输入:
A 3 5
A 4 2
Qx 4
R 4 2
A 4 3
Qy 3
输入数据的每一行,格式为以下之一:
A x y
R x y
Qx x
Qy y
其中 x 与 y 都是 0 到 10^9 之间的整数
A x y 表示插入点 (x, y)
R x y 表示删除点 (x, y),保证存在
Qx x 表示在当前所有点中,找到第一维为x的点,输出其第二维的值,保证存在
Qy y 表示在当前所有点中,找到第二维为y的点,输出其第一维的值,保证存在
总共操作数不超过100000
输出:
2
4
对于每一个 Qx 和 Qy 操作,输出一行表示对应的答案
*/
#include
#include
#include
using namespace std;
// 在此处补充你的代码
struct myComp {
bool operator()(const pair &a, const pair &b) {
if (a.first > 0 && a.second > 0 && b.first > 0 && b.second > 0) {
return a.first > b.first; // x 值大小排序
} else if (a.first < 0 || b.first < 0) {
return a.second < b.second; // y 值大小排序
} else if (a.second < 0 || b.second < 0) {
return a.first > b.first; // x 值大小排序
}
return true;
}
};
int main() {
string cmd;
set, myComp> S; // 模板类型 myComp
while (cin >> cmd) {
if (cmd == "A") {
int x, y;
cin >> x >> y;
S.insert(make_pair(x, y)); //插入一个点
} else if (cmd == "Qx") {
int x;
cin >> x;
cout << S.lower_bound( make_pair(x, -1) )->second << endl;//返回大于等于x的第一个位置的迭代器
} else if (cmd == "Qy") {
int y;
cin >> y;
cout << S.lower_bound(make_pair(-1, y))->first << endl; //返回大于等于y的第一个位置的迭代器
} else {
int x, y;
cin >> x >> y;
S.erase(make_pair(x, y)); //删除一个点
}
}
return 0;
}
set嵌套及比较函数使用
#include
#include
using namespace std;
struct weapon
{
int number;
int power;
weapon(int n,int p):number(n),power(p) //构造
{
}
bool operator < (const weapon &w) const/* 键比较大小 const 函数(常函数)*/
{
if( number == w.number ) //里层同类有序
return power < w.power;
return number < w.number;
}
/* friend bool operator < (const weapon& w1,const weapon& w2)//比较函数 ( 友元 )
{
if( w1.number == w2.number ) //里层同类有序
return w1.power < w2.power;
return w1.number < w2.number; //外层不同类有序
} */
}sword(0,100),bomb(1,105),arrow(2,103),bomb2(1,99);
int main()
{
set > wset;
set w1,w2,w3;
w1.insert(sword);
w2.insert(bomb);
w2.insert(bomb2);
w3.insert(arrow);
wset.insert(w2);
wset.insert(w3);
wset.insert(w1);
set > ::iterator it = wset.begin();
int n = wset.size();
while(n--)
{
set ::iterator wit = it->begin(); //(*it).begin();
int cnt = it->size();
while(cnt--)
{
cout << "power = " << wit->power << "\t, num = " << wit -> number << endl;
wit++;
}
cout << "---------------------------" << endl;
it++;
}
return 0;
}
武器编号小的在前,编号相同的,攻击低的在前的代码实现:
#include
#include
using namespace std;
struct weapon
{
int number;
int power;
weapon(int n,int p):number(n),power(p)
{
}
bool operator < (const weapon &w) const
{
if( number == w.number )
return power < w.power;
return number < w.number;
}
}sword(0,100),bomb(1,105),arrow(2,103),bomb2(1,99),arrow2(2,50);
int main()
{
set wset;
//wset.insert(sword);
wset.insert(bomb);
wset.insert(bomb2);
wset.insert(arrow);
wset.insert(arrow2);
set ::iterator it = wset.begin();
int n = wset.size();
while(n--)
{
cout << "power = " << it->power << "\t, num = " << it -> number << endl;
cout << "---------------------------" << endl;
it++;
}
return 0;
}
每个武器的编号、攻击力及这种武器的数量,有序:武器编号小的在前,编号相同的,攻击低的在前,enum、struct、pair、static、set
#include
#include
using namespace std;
enum { SWORD, BOMB, ARROW, WEAPON_SIZE } ;
struct weapon
{
pair number_power; //编号及个数
static int count[WEAPON_SIZE];
weapon(int n,int p):number_power( n,p )
{
count[number_power.first]++;
}
bool operator < (const weapon &w) const
{
if( number_power.first == w.number_power.first )
return number_power.second < w.number_power.second;
return number_power.first < w.number_power.first;
}
}sword( SWORD,100 ),
bomb( BOMB,105 ),
arrow( ARROW,103 ),
bomb2( BOMB,99 ),
arrow2( ARROW,50 )
;
int weapon::count[WEAPON_SIZE] = { 0 };
int main()
{
set wset;
//wset.insert(sword);
wset.insert(bomb);
wset.insert(bomb2);
wset.insert(arrow);
wset.insert(arrow2);
set ::iterator it = wset.begin();
/* int n = wset.size();
while(n--)
{
cout << "power = " << it->number_power.second
<< "\t, num = " << it ->number_power.first << endl;
cout << "count = " << weapon::count[ it ->number_power.first ] << endl;
cout << "---------------------------" << endl;
it++;
} */
int n = it ->number_power.first;
while( it ->number_power.first == n )
{
cout << "power = " << it->number_power.second
<< "\t, num = " << it ->number_power.first << endl;
cout << "count = " << weapon::count[ it ->number_power.first ] << endl;
cout << "---------------------------" << endl;
it++;
}
return 0;
}
c++语言中,multiset 是
/*
输入n个整数,输出整数数列中大小排名前k的偶数
测试用例:
2
9 4
1 2 4 3 6 6 7 8 9
3 2
18 16 14
*/
#include
#include
using namespace std;
class MyQueue
{
int k; //创建对象时,k表示前k个偶数整数
multiset < int, greater > que; //multiset容器对象 元素有序且可以重复
public:
MyQueue(int k):k(k) {}
//容器插入对象
friend istream & operator>>(istream&is, MyQueue &a) //对象输入 重载 >> 运算符
{
int num;
is >> num;
if (num % 2 == 0)
{
a.que.insert(num); //是偶数插入
}
return is;
}
//从容器输出对象
friend ostream & operator <<(ostream&os, MyQueue &a) //对象输出 重载 << 运算符
{
multiset::iterator p = a.que.begin(); //迭代器
int count = 0;
for (; count < a.k; p++)
{
if (count){
os << " ";
}
os << *p ; //输出元素
count++; //记录输出元素个数
}
return os;
}
};
int main()
{
int t;
cin >> t;
while(t--)
{
int n, k;
cin >> n >> k;
MyQueue q(k);
for (int i = 0; i < n; ++i)
cin >> q; //利用>>运算符重载 输入整数(插入到对象 q 的 multiset 容器中)
cout<
multiset 容器,矩形类对象大小排序,默认 <运算符重载 (< 双目运算符,友元函数 ), 模板类型(友元类),函数对象,()运算符重载,注:何时使用友元?当你想要用普通函数或非本类的成员函数,调用本类的私有成员时
/* 矩形排序
给定一系列边长已知的矩形,输出对矩形进行两种排序的结果。
在第一种排序中,先按矩形的面积从大到小排序;若两个矩形的面积相同,则周长大的排在前。
在第二种排序中,先按矩形的周长从小到大排序;若两个矩形的周长相同,则面积小的排在前。
输入:
6
3 8
4 6
10 2
6 6
4 8
3 6
第一行是一个整数n,表示输入的矩形个数。
接下来n行表示了n个矩形。每行有两个整数a与b,表示该矩形的长与宽。
输出:
36 24
32 24
24 22
24 20
20 24
18 18
18 18
24 20
24 22
20 24
32 24
36 24 */
#include
#include
using namespace std;
// 在此处补充你的代码
class Rectangle
{
int length, width, area, perimeter; //长、宽、面积、直径
public:
friend class Comp; //友元类 可以处理 Rectangle 类的数据成员
Rectangle(int _length, int _width) : length(_length), width(_width) //构造函数
{
area = length * width;
perimeter = 2 * (length + width);
}
//友元函数 比较对象大小
friend bool operator<(const Rectangle &rec1, const Rectangle &rec2) // < 运算符重载
{
if (rec1.area == rec2.area) //面积相等 直径大的在前
return rec1.perimeter > rec2.perimeter;
return rec1.area > rec2.area; //面积大的在前
}
//输出对象
friend ostream &operator<<(ostream &os, const Rectangle &obj) // 友元函数 << 运算符重载 输出面积及直径
{
cout << obj.area << ' ' << obj.perimeter;
return os;
}
};
class Comp
{
public:
bool operator()(const Rectangle &rec1, const Rectangle &rec2) //比较对象大小
{
if (rec1.perimeter == rec2.perimeter) //直径相等 面积小的在前
return rec1.area < rec2.area;
return rec1.perimeter < rec2.perimeter; //直径小的在前
}
};
int main()
{
multiset m1; //默认 < 运算符重载 友元函数
multiset m2; //模板 Comp类型 函数对象(临时对象) Rectangle类的友元类 < 运算符重载
int n, a, b;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> a >> b;
m1.insert(Rectangle(a, b));
m2.insert(Rectangle(a, b));
}
for (multiset::iterator it = m1.begin(); it != m1.end(); it++) {
cout << *it << endl;
}
cout << endl;
for (multiset::iterator it = m2.begin(); it != m2.end(); it++) {
cout << *it << endl;
}
return 0;
}
2、
临时对象,就是一种无名对象(unamed objects),临时对象:类名之后直接加一对小括号 () 或者大括号 {}(列表初始化),并可指定初值,其意义相当于调用相应的构造函数并且不指定对象名
函数对象(function object),形式上是一个类实例化的对象,本质上是为了实现某种与函数等价的功能,函数对象的思想是:用类来封装一个函数功能,然后用这个类实例化不同的函数对象,若一个类重载了运算符(),则该类的对象就成为函数对象 注:重载()运算符,参数没有限制,比如:bool operator()(int a,int b,int c){...}
/*
完成以下程序,使得输入的整数x,以及若干正整数,将
大于x的正整数输出;然后输入若干字符串,将字符串长度大于x的字符串输出
测试用例:
2
5 6
1 3 59 30 2 40
this is hello please me ha
1 1
4
this
输出:
59,30,40,
please,
4,
this,
*/
#include //for_each 头文件
#include
#include
using namespace std;
class Printer
{
int size;
public:
Printer(int x) : size(x) {}
void operator()(int x) //运算符()重载
{
if (x > size)
cout << x << ',';
}
void operator()(string str) //运算符()重载
{
if (str.size() > size)
cout << str << ',';
}
};
int main()
{
int t;
cin >> t;
while(t--)
{
int n,x;
cin >> x >> n;
vector intVec;
for(int i = 0; i < n; ++i)
{
int y;
cin >> y;
intVec.push_back(y);
}
for_each(intVec.begin(), intVec.end(), Printer(x)); //Printer(x)是函数对象
cout << endl;
vector strVec;
for(int i = 0; i < n; ++i)
{
string str;
cin >> str;
strVec.push_back(str);
}
for_each(strVec.begin(), strVec.end(), Printer(x));
cout << endl;
}
return 0;
}
全局函数:
#include
#include
#include //for_each
using namespace std;
//全局函数
void printElem(int elem, const char* prefix)
{
cout << prefix << elem << endl;
}
int main()
{
int ia[] = {1, 2, 3};
vector ivec(ia, ia + sizeof(ia) / sizeof(int));
for_each(ivec.begin(), ivec.end(), bind2nd(ptr_fun(printElem), "Element:"));
return 0;
}
lambda表达式:
#include
#include
#include
using namespace std;
int main()
{
int i = 3;
vector v;
while(i--)
{
char* p = new char(128);
cin >> p;
v.push_back(p);
}
//遍历的3种方法
for_each( v.begin(),v.end(),[=](char*str){ cout << str << endl; } );
/* for(vector::iterator it= v.begin();it!=v.end();++it)
{
cout << (*it) << endl;
} */
/* for( char*str:v ){
cout << str << endl;
} */
return 0;
}
3、 容器的 sort 参数:< 运算符重载,函数对象(重载 () 运算符),全局函数,
容器的 for_each 的参数为全局函数
/*
三生三世
测试用例:3代表3个电视剧,以下是 每个电视剧的剧名 及 演员阵容、剧情和演技的分数
3
In the Name of People
98 97 99
Life After Life, Blooms Over Blooms
99 82 73
Ming Dynasty: 1566
97 100 100
输出:按分数(分别为演员阵容、剧情和演技的分数)从大到小排序3次,并按排序输出剧名
*/
#include //string
#include //list
#include // sort
using namespace std;
class TV_Drama {
public:
char name[100]; //电视剧
int actor; //演员阵容评分
int story; //剧情评分
int acting_skill; //演技评分
// 在此处补充你的代码
TV_Drama(string _name, int _actor, int _story, int _acting_skill) :
actor(_actor), story(_story), acting_skill(_acting_skill) {
_name.copy(name, _name.size(), 0); //string类的函数
name[_name.size()] = 0; //字符串结束符 name 电视剧剧名
}
bool operator <(const TV_Drama &obj) { //对象比较,重载比较运算符 <
return actor > obj.actor; //从高到低排序
}
};
void Printer(const TV_Drama &obj) { //全局函数
cout << obj.name << ';';
//cout <<"--" << obj.actor << "--" << obj.story << "--" << obj.acting_skill<< endl;
}
bool comparator_1(const TV_Drama &o1, const TV_Drama &o2) { //全局函数
return o1.story > o2.story; //从高到低排序
}
class comparator_2 { //函数对象 ,重载了小括号 () 运算符
public:
bool operator()(const TV_Drama &o1, const TV_Drama &o2) {
return o1.acting_skill > o2.acting_skill; //从高到低排序
}
};
int main() {
list lst; //对象容器
int n;
cin >> n;
char _name[100];
int _actor, _story, _acting_skill;
for (int i = 0; i < n; i++) {
cin.ignore(); //cin.ignore()函数用于忽略或清除输入缓冲区中的一个或多个字符
cin.getline(_name, 100);
cin >> _actor >> _story >> _acting_skill;
lst.push_back(TV_Drama(_name, _actor, _story, _acting_skill));
}
lst.sort(); //无参 默认对象从小到大,重载 < 运算符改为 从大到小
for_each(lst.begin(), lst.end(), Printer);
cout << endl;
lst.sort(comparator_1); //全局函数
for_each(lst.begin(), lst.end(), Printer);
cout << endl;
lst.sort(comparator_2()); //函数对象
for_each(lst.begin(), lst.end(), Printer);
cout << endl;
return 0;
}
4、
#include
#include
5、
#include
#include
#include //priority_queue
using namespace std;
struct weapon
{
int number;
int power;
weapon(int n,int p):number(n),power(p)
{
}
bool operator < (const weapon &w) const
{
if( number == w.number )
return power > w.power; //!!!
return number > w.number; //!!!
}
}sword(0,100),bomb(1,105),arrow(2,103),bomb2(1,99),arrow2(2,50);
int main()
{
priority_queue pqw;
pqw.push(sword);
pqw.push(bomb);
pqw.push(arrow);
pqw.push(bomb2);
pqw.push(arrow2);
while (!pqw.empty())
{
cout << pqw.top().number << "," << pqw.top().power << endl;
pqw.pop();
}
return 0;
}
二、算法
无论一个STL算法返回什么,它都不会是实参的容器,传递给STL算法的实参是迭代器,算法完全不了解迭代器所指向的数据结构,迭代器的存在主要是为了将算法从它所处理的数据结构上分离出来
C++标准将算法分成4组:非修改式序列操作、修改式序列操作、排序和相关操作、数值运算
1、非修改式操作序列
不修改序列的算法只读取输入序列中元素的值,而不会重排序列或是改变元素值,用户提供给算法的操作一般也不会改变元素值,这些操作通常是谓词(不会修改实参)for_each(),它简单地对序列中的每个元素执行指定的操作,传递给for_each()的操作可能会修改元素,例如:
void increment_all(vector& v)
{
for_each(v.begin(),v.end(),[](int&x){ ++x; });
}
2、修改式序列操作
3、排序和相关操作
对 vector排序:武器编号小的在前,编号相同的,攻击低的在前的代码实现:
#include
#include
#include //sort
using namespace std;
struct weapon
{
int number;
int power;
weapon(int n,int p):number(n),power(p)
{
}
bool operator < (const weapon &w) const
{
if( number == w.number )
return power < w.power;
return number < w.number;
}
}sword(0,100),bomb(1,105),arrow(2,103),bomb2(1,99),arrow2(2,50);
int main()
{
vector vw;
vw.push_back(sword);
vw.push_back(bomb);
vw.push_back(arrow);
vw.push_back(bomb2);
vw.push_back(arrow2);
sort(vw.begin(),vw.end()); //排序算法sort
for(vector::iterator it=vw.begin(); it!=vw.end(); ++it)
{
cout << it->number << "," << it->power << endl;
}
return 0;
}
4、数值运算
又见模板,模板,[]运算符重载,成员函数
/*
又见模板
输入:
1
1 2 3 4 5 6 7 8 9 10
4.2 0.0 3.1 2.7 5.2
Hello , world !
第一行是整数n,表示有n组数据
每组数据有3行
第一行是10个整数
第二行是5个小数
第三行是4个不带空格的字符串,它们之间用空格分隔
输出:
3
15.2
Hello,world!
*/
#include
#include
using namespace std;
// 在此处补充你的代码
template
class A
{
T *p; //指针
public:
A(T *obj) : p(new T[size])
{
for (int i = 0; i < size; i++)
p[i] = obj[i];
}
T &operator[](int n) { return p[n]; } //[]运算符重载
T sum()
{
T su = *p;
for (int i = 1; i < size; i++)
su += p[i]; //string 类 += 是字符串连接
return su;
}
};
int main()
{
int t;
cin >> t;
while( t -- )
{ //1、int类型 数组
int b1[10];
for(int i = 0;i < 10; ++i)
cin >> b1[i];
A a1 = b1; //构造函数
cout << a1[2] << endl; // []运算符重载
//2、double类型 数组
double b2[5] ;
for(int i = 0;i < 5; ++i)
cin >> b2[i];
A a2 = b2; //构造函数
cout << a2.sum() << endl; // sum成员函数
//3、string类型 数组
string b3[4] ;
for(int i = 0;i < 4; ++i)
cin >> b3[i];
A a3 = b3; //构造函数
cout << a3.sum() << endl; // 调用sum成员函数
}
return 0;
}
魔兽世界的西面是红魔军的司令部,东面是蓝魔军的司令部。两个司令部之间是依次排列的若干城市,城市从西向东依次编号为1,2,3 .... N ( N <= 20 )。红魔军的司令部算作编号为0的城市,蓝魔军的司令部算作编号为N+1的城市。司令部有生命元,用于制造武士。
两军的司令部都会制造武士。武士一共有 dragon 、ninja、iceman、lion、wolf 五种。每种武士都有编号、生命值、攻击力这三种属性。
双方的武士编号都是从1开始计算。红方制造出来的第 n 个武士,编号就是n。同样,蓝方制造出来的第 n 个武士,编号也是n。
武士在刚降生的时候有一个初始的生命值,生命值在战斗中会发生变化,如果生命值减少到0(生命值变为负数时应当做变为0处理),则武士死亡(消失)。
有的武士可以拥有武器。武器有三种,sword, bomb,和arrow,编号分别为0,1,2。
武士降生后就朝对方司令部走,在经过的城市如果遇到敌人(同一时刻每个城市最多只可能有1个蓝武士和一个红武士),就会发生战斗。每次战斗只有一方发起主动进攻一次。被攻击者生命值会减去进攻者的攻击力值和进攻者手中sword的攻击力值。被进攻者若没死,就会发起反击,被反击者的生命值要减去反击者攻击力值的一半(去尾取整)和反击者手中sword的攻击力值。反击可能致敌人于死地。
如果武士在战斗中杀死敌人(不论是主动进攻杀死还是反击杀死),则其司令部会立即向其发送8个生命元作为奖励,使其生命值增加8。当然前提是司令部得有8个生命元。如果司令部的生命元不足以奖励所有的武士,则优先奖励距离敌方司令部近的武士。
如果某武士在某城市的战斗中杀死了敌人,则该武士的司令部立即取得该城市中所有的生命元。注意,司令部总是先完成全部奖励工作,然后才开始从各个打了胜仗的城市回收生命元。对于因司令部生命元不足而领不到奖励的武士,司令部也不会在取得战利品生命元后为其补发奖励。
如果一次战斗的结果是双方都幸存(平局),则双方都不能拿走发生战斗的城市的生命元。
城市可以插旗子,一开始所有城市都没有旗子。在插红旗的城市,以及编号为奇数的无旗城市,由红武士主动发起进攻。在插蓝旗的城市,以及编号为偶数的无旗城市,由蓝武士主动发起进攻。
当某个城市有连续两场战斗都是同一方的武士杀死敌人(两场战斗之间如果有若干个战斗时刻并没有发生战斗,则这两场战斗仍然算是连续的;但如果中间有平局的战斗,就不算连续了) ,那么该城市就会插上胜方的旗帜,若原来插着败方的旗帜,则败方旗帜落下。旗帜一旦插上,就一直插着,直到被敌人更换。一个城市最多只能插一面旗帜,旗帜没被敌人更换前,也不会再次插同颜色的旗。
各种武器有其特点:
sword武器的初始攻击力为拥有它的武士的攻击力的20%(去尾取整)。但是sword每经过一次战斗(不论是主动攻击还是反击),就会变钝,攻击力变为本次战斗前的80% (去尾取整)。sword攻击力变为0时,视为武士失去了sword。如果武士降生时得到了一个初始攻击力为0的sword,则视为武士没有sword.
arrow有一个攻击力值R。如果下一步要走到的城市有敌人,那么拥有arrow的武士就会放箭攻击下一个城市的敌人(不能攻击对方司令部里的敌人)而不被还击。arrow使敌人的生命值减少R,若减至小于等于0,则敌人被杀死。arrow使用3次后即被耗尽,武士失去arrow。两个相邻的武士可能同时放箭把对方射死。
拥有bomb的武士,在战斗开始前如果判断自己将被杀死(不论主动攻击敌人,或者被敌人主动攻击都可能导致自己被杀死,而且假设武士可以知道敌人的攻击力和生命值),那么就会使用bomb和敌人同归于尽。武士不预测对方是否会使用bomb。
武士使用bomb和敌人同归于尽的情况下,不算是一场战斗,双方都不能拿走城市的生命元,也不影响城市的旗帜。
不同的武士有不同的特点。
dragon可以拥有一件武器。编号为n的dragon降生时即获得编号为 n%3 的武器。dragon还有“士气”这个属性,是个浮点数,其值为它降生后其司令部剩余生命元的数量除以造dragon所需的生命元数量。dragon 在一次在它主动进攻的战斗结束后,如果还没有战死,而且士气值大于0.8,就会欢呼。dragon每取得一次战斗的胜利(敌人被杀死),士气就会增加0.2,每经历一次未能获胜的战斗,士气值就会减少0.2。士气增减发生在欢呼之前。
ninja可以拥有两件武器。编号为n的ninja降生时即获得编号为 n%3 和 (n+1)%3的武器。ninja 挨打了也从不反击敌人。
iceman有一件武器。编号为n的iceman降生时即获得编号为 n%3 的武器。iceman 每前进两步,在第2步完成的时候,生命值会减少9,攻击力会增加20。但是若生命值减9后会小于等于0,则生命值不减9,而是变为1。即iceman不会因走多了而死。
lion 有“忠诚度”这个属性,其初始值等于它降生之后其司令部剩余生命元的数目。每经过一场未能杀死敌人的战斗,忠诚度就降低K。忠诚度降至0或0以下,则该lion逃离战场,永远消失。但是已经到达敌人司令部的lion不会逃跑。Lion在己方司令部可能逃跑。lion 若是战死,则其战斗前的生命值就会转移到对手身上。所谓“战斗前”,就是每个小时的40分前的一瞬间。
wolf降生时没有武器,但是在战斗中如果获胜(杀死敌人),就会缴获敌人的武器,但自己已有的武器就不缴获了。被缴获的武器当然不能算新的,已经被用到什么样了,就是什么样的。
以下是不同时间会发生的不同事件:
在每个整点,即每个小时的第0分, 双方的司令部中各有一个武士降生。
红方司令部按照 iceman、lion、wolf、ninja、dragon 的顺序制造武士。
蓝方司令部按照 lion、dragon、ninja、iceman、wolf 的顺序制造武士。
制造武士需要生命元。
制造一个初始生命值为 m 的武士,司令部中的生命元就要减少 m 个。
如果司令部中的生命元不足以制造某武士,那么司令部就等待,直到获得足够生命元后的第一个整点,才制造该武士。例如,在2:00,红方司令部本该制造一个 wolf ,如果此时生命元不足,那么就会等待,直到生命元足够后的下一个整点,才制造一个 wolf。
在每个小时的第5分,该逃跑的lion就在这一时刻逃跑了。
在每个小时的第10分:所有的武士朝敌人司令部方向前进一步。即从己方司令部走到相邻城市,或从一个城市走到下一个城市。或从和敌军司令部相邻的城市到达敌军司令部。
在每个小时的第20分:每个城市产出10个生命元。生命元留在城市,直到被武士取走。
在每个小时的第30分:如果某个城市中只有一个武士,那么该武士取走该城市中的所有生命元,并立即将这些生命元传送到其所属的司令部。
在每个小时的第35分,拥有arrow的武士放箭,对敌人造成伤害。放箭事件应算发生在箭发出的城市。注意,放箭不算是战斗,因此放箭的武士不会得到任何好处。武士在没有敌人的城市被箭射死也不影响其所在城市的旗帜更换情况。
在每个小时的第38分,拥有bomb的武士评估是否应该使用bomb。如果是,就用bomb和敌人同归于尽。
在每个小时的第40分:在有两个武士的城市,会发生战斗。 如果敌人在5分钟前已经被飞来的arrow射死,那么仍然视为发生了一场战斗,而且存活者视为获得了战斗的胜利。此情况下不会有“武士主动攻击”,“武士反击”,“武士战死”的事件发生,但战斗胜利后应该发生的事情都会发生。如Wolf一样能缴获武器,旗帜也可能更换,等等。在此情况下,Dragon同样会通过判断是否应该轮到自己主动攻击来决定是否欢呼。
在每个小时的第50分,司令部报告它拥有的生命元数量。
在每个小时的第55分,每个武士报告其拥有的武器情况。
武士到达对方司令部后就算完成任务了,从此就呆在那里无所事事。
任何一方的司令部里若是出现了2个敌人,则认为该司令部已被敌人占领。
任何一方的司令部被敌人占领,则战争结束。战争结束之后就不会发生任何事情了。
给定一个时间,要求你将从0点0分开始到此时间为止的所有事件按顺序输出。事件及其对应的输出样例如下:
1) 武士降生
输出样例: 000:00 blue lion 1 born
表示在 0点0分,编号为1的蓝魔lion武士降生
如果造出的是dragon,那么还要多输出一行,例:
000:00 blue dragon 1 born
Its morale is 23.34
表示该该dragon降生时士气是23. 34(四舍五入到小数点后两位)
如果造出的是lion,那么还要多输出一行,例:
000:00 blue lion 1 born
Its loyalty is 24
表示该lion降生时的忠诚度是24
2) lion逃跑
输出样例: 000:05 blue lion 1 ran away
表示在 0点5分,编号为1的蓝魔lion武士逃走
3) 武士前进到某一城市
输出样例: 000:10 red iceman 1 marched to city 1 with 20 elements and force 30
表示在 0点10分,红魔1号武士iceman前进到1号城市,此时他生命值为20,攻击力为30
对于iceman,输出的生命值和攻击力应该是变化后的数值
4)武士放箭
输出样例: 000:35 blue dragon 1 shot
表示在 0点35分,编号为1的蓝魔dragon武士射出一支箭。如果射出的箭杀死了敌人,则应如下输出:
000:35 blue dragon 1 shot and killed red lion 4
表示在 0点35分,编号为1的蓝魔dragon武士射出一支箭,杀死了编号为4的红魔lion。
5)武士使用bomb
输出样例: 000:38 blue dragon 1 used a bomb and killed red lion 7
表示在 0点38分,编号为1的蓝魔dragon武士用炸弹和编号为7的红魔lion同归于尽。
6) 武士主动进攻
输出样例:000:40 red iceman 1 attacked blue lion 1 in city 1 with 20 elements and force 30
表示在0点40分,1号城市中,红魔1号武士iceman 进攻蓝魔1号武士lion,在发起进攻前,红魔1号武士iceman生命值为20,攻击力为 30
7) 武士反击
输出样例:001:40 blue dragon 2 fought back against red lion 2 in city 1
表示在1点40分,1号城市中,蓝魔2号武士dragon反击红魔2号武士lion
8) 武士战死
输出样例:001:40 red lion 2 was killed in city 1
被箭射死的武士就不会有这一条输出。
9) 武士欢呼
输出样例:003:40 blue dragon 2 yelled in city 4
10) 武士获取生命元( elements )
输出样例:001:40 blue dragon 2 earned 10 elements for his headquarter
输出不包括在30分不是通过战斗获取的elements
11) 旗帜升起
输出样例:004:40 blue flag raised in city 4
12) 武士抵达敌军司令部
输出样例:001:10 red iceman 1 reached blue headquarter with 20 elements and force 30
(此时他生命值为20,攻击力为30)对于iceman,输出的生命值和攻击力应该是变化后的数值
13) 司令部被占领
输出样例:003:10 blue headquarter was taken
14)司令部报告生命元数量
000:50 100 elements in red headquarter
000:50 120 elements in blue headquarter
表示在0点50分,红方司令部有100个生命元,蓝方有120个
15)武士报告武器情况
000:55 blue wolf 2 has arrow(2),bomb,sword(23)
000:55 blue wolf 4 has no weapon
000:55 blue wolf 5 has sword(20)
表示在0点55分,蓝魔2号武士wolf有一支arrow(这支arrow还可以用2次),一个bomb,还有一支攻击力为23的sword。
蓝魔4号武士wolf没武器。
蓝魔5号武士wolf有一支攻击力为20的sword。
交代武器情况时,次序依次是:arrow,bomb,sword。如果没有某种武器,某种武器就不用提。报告时,先按从西向东的顺序所有的红武士报告,然后再从西向东所有的蓝武士报告。
输出事件时:
首先按时间顺序输出;
同一时间发生的事件,按发生地点从西向东依次输出. 武士前进的事件, 算是发生在目的地。
在一次战斗中有可能发生上面的 6 至 11 号事件。这些事件都算同时发生,其时间就是战斗开始时间。一次战斗中的这些事件,序号小的应该先输出。
两个武士同时抵达同一城市,则先输出红武士的前进事件,后输出蓝武士的。
显然,13号事件发生之前的一瞬间一定发生了12号事件。输出时,这两件事算同一时间发生,但是应先输出12号事件
虽然任何一方的司令部被占领之后,就不会有任何事情发生了。但和司令部被占领同时发生的事件,全都要输出。
输入
第一行是t,代表测试数据组数
每组样例共三行。
第一行,五个整数 M,N,R,K, T。其含义为:
每个司令部一开始都有M个生命元( 1 <= M <= 10000)
两个司令部之间一共有N个城市( 1 <= N <= 20 )
arrow的攻击力是R
lion每经过一场未能杀死敌人的战斗,忠诚度就降低K。
要求输出从0时0分开始,到时间T为止(包括T) 的所有事件。T以分钟为单位,0 <= T <= 5000
第二行:五个整数,依次是 dragon 、ninja、iceman、lion、wolf 的初始生命值。它们都大于0小于等于10000
第三行:五个整数,依次是 dragon 、ninja、iceman、lion、wolf 的攻击力。它们都大于0小于等于10000
输出
对每组数据,先输出一行:
Case n:
如对第一组数据就输出 Case1:
然后按恰当的顺序和格式输出到时间T为止发生的所有事件。每个事件都以事件发生的时间开头,时间格式是“时: 分”,“时”有三位,“分”有两位。
样例输入
1
20 1 10 10 1000
20 20 30 10 20
5 5 5 5 5
样例输出
Case 1:
000:00 blue lion 1 born
Its loyalty is 10
000:10 blue lion 1 marched to city 1 with 10 elements and force 5
000:30 blue lion 1 earned 10 elements for his headquarter
000:50 20 elements in red headquarter
000:50 20 elements in blue headquarter
000:55 blue lion 1 has no weapon
001:00 blue dragon 2 born
Its morale is 0.00
001:10 blue lion 1 reached red headquarter with 10 elements and force 5
001:10 blue dragon 2 marched to city 1 with 20 elements and force 5
001:30 blue dragon 2 earned 10 elements for his headquarter
001:50 20 elements in red headquarter
001:50 10 elements in blue headquarter
001:55 blue lion 1 has no weapon
001:55 blue dragon 2 has arrow(3)
002:10 blue dragon 2 reached red headquarter with 20 elements and force 5
002:10 red headquarter was taken
#include
#include
#include
#include
using namespace std;
enum Knight_name{dragon, ninja, iceman, lion, wolf};//武士名称
enum Weapon_name{sword, bomb, arrow};//武器名称
string Knight[5] = {"dragon", "ninja", "iceman", "lion", "wolf"};//武士名称,输出使用
Knight_name Order[2][5] = {{iceman, lion, wolf, ninja, dragon},//制造顺序
{lion, dragon, ninja, iceman, wolf}};
string Color[2] = {"red", "blue"};//司令部颜色,输出使用
string Weapons_[3] = {"sword", "bomb", "arrow"};//武器名称,输出使用
int Attack_[5];//各武士初始攻击力
int Loyal_reduce;//lion未杀死敌人所减少士气
int Hour, Minute;//计时器
int Total_Minutes;//终止时间
int Life_Make[5];//制造各种武士所需生命元
int arrow_attack;//arrow攻击力
void Print_time(){//输出前面时间
cout.width(3); cout.fill('0');
cout << Hour << ':';cout.width(2);
cout << Minute << ' ';
}
class City;
class Command;
class Weapon{//武器
private:
int name, sword_attack, arrow_usetime;//武器名称,sword攻击力,arrow剩余使用次数
public:
Weapon(int i, int satt):name(i), sword_attack(satt),arrow_usetime(3){}//武器状态初始化
bool sword_dull(){//sword变钝
sword_attack = int (sword_attack * 0.8);
return sword_attack;
}
int &usetime(){return arrow_usetime;}
int sw_atk(){return sword_attack;}
};
class Warrior{//士兵
private:
int Num, Life, Attack, Loyal, Step, l_life;//编号,生命力,攻击力,忠诚度,步数
Knight_name name;//武士名称
double Morale;//士气
City* City_Belong_to;//所属城市
Command* Command_Belong_to;//所属司令部
bool If_win,If_kill;//战斗是否获胜,是否杀死敌人
Weapon* weapon[3];//装备
public:
Warrior(int n, Knight_name &name_, int &life, int &t_life,Command *COMD){//初始化士兵属性
Num = n; name = name_; Life = life; Attack = Attack_[name]; Step = 0; l_life = 0;
weapon[0] = NULL; weapon[1] = NULL; weapon[2] = NULL;
switch(name){
case dragon:case iceman: weapon[Num % 3] = new Weapon(Num % 3, int(Attack_[name] * 0.2)); break;
case ninja: weapon[Num % 3] = new Weapon(Num % 3, int(Attack_[name] * 0.2));
weapon[(Num + 1) % 3] = new Weapon((Num + 1) % 3, int(Attack_[name] * 0.2)); break;
default: break;
};
if (weapon[sword]) if (!weapon[sword]->sw_atk()) weapon[sword] = NULL;//若初始武器攻击为0,则delete
Morale = double(t_life) / double(Life);
Loyal = t_life; If_win = false; If_kill = false;
City_Belong_to = NULL; Command_Belong_to = COMD;
cout << Knight[name] << ' ' << Num << " born\n";
if (name == dragon){
cout << "Its morale is ";
cout.precision(2);
cout << fixed << Morale << endl;
}
if (name == lion){cout << "Its loyalty is " << Loyal << endl;}
}
bool &IF_win(){return If_win;}
int life(){return Life;}
bool Minute_5();//lion是否逃跑 输出
void Minute_10(bool );//武士前进输出
void Minute_30(int );//获取城市生命元及输出
void arrow_shot();//使用弓箭输出
void Be_shoted();//被射中处理及输出
void Change_City(City * Cp){City_Belong_to = Cp;}
void Morale_Change(){If_win ? Morale += 0.2: Morale -=0.2;}
bool weapon_(Weapon_name name){return weapon[name];}
void Use_bomb(Warrior *);//使用bomb输出
int fight(Warrior* Wp){//假设战斗,判断是否会获胜
if (Life > 0 and Wp->Life > 0){
int swatk = 0;
if (weapon[sword]) swatk = weapon[sword]->sw_atk();
if (Wp->Life - Attack- swatk > 0){
if (Wp->name == ninja) return 0;
else{
int E_swatk = 0;
if (Wp->weapon[sword]) E_swatk = (Wp->weapon[sword])->sw_atk();
if (Life - (Wp->Attack / 2) - E_swatk > 0) return 0;
else return -1;
}
}else return 1;
}
return 0;
}
bool bomb(Warrior *, int);//判断是否使用bomb
void Fight(Warrior *);//武士战斗处理及输出
void Dead();//武士死亡输出
void account(Warrior * Wp){//部分战后处理
If_win = true;
if(If_kill) {Wp->Dead();If_kill = false;}
if (Wp->name == lion) Life += Wp->l_life;
if (name == wolf)
for (int i = 0; i < 3; ++i)
if (Wp->weapon[i] and !weapon[i]){
weapon[i] = Wp->weapon[i];
Wp->weapon[i] = NULL;
}
Morale_Change();
}
void Reward();//战胜后获取奖励
void ADD(int);//所属司令部增加生命元
void Loyal_Reduce(){Loyal -= Loyal_reduce;}
void Report_weapon();//报告武器使用情况
~Warrior(){
for (int i = 0; i < 3; ++i)
if (weapon[i]) delete weapon[i];
}
};
class City{
private:
int Number, Life, Flag, Flag_G[2];//城市编号,生命元,旗帜,各方士兵连续胜利场次
Warrior *Warrior_In_City[2];
public:
int Num(){return Number;}
int Life_(){return Life;}
City(int N){
Number = N; Life = 0; Flag = -1;//-1 表示无旗城市
Warrior_In_City[0] = NULL; Flag_G[0] = 0;
Warrior_In_City[1] = NULL; Flag_G[1] = 0;
}
void Minute_5(){//处理逃跑lion
for(int i = 0; i < 2; ++i)
if(Warrior_In_City[i]) if (Warrior_In_City[i]->Minute_5()){
delete Warrior_In_City[i]; Warrior_In_City[i] = NULL;
}
}
void Move(City* Cp, int i){//warrior前进
Warrior_In_City[i] = Cp->Warrior_In_City[i];
if(Warrior_In_City[i]) Warrior_In_City[i]->Change_City(this);
}
void Move(Command *, int);//warrior进入敌方司令部
void Move(Warrior *Wp, int i){//warrior从command进入city
Warrior_In_City[i] = Wp;
if (Warrior_In_City[i]) Warrior_In_City[i]->Change_City(this);
}
bool If_exist(int i){return Warrior_In_City[i];}
void Minute_10(){//warrior前进输出
if (Warrior_In_City[0]) Warrior_In_City[0]->Minute_10(false);
if (Warrior_In_City[1]) Warrior_In_City[1]->Minute_10(false);
}
void Add_Life(){Life += 10;}
void Minute_30(){//城内单独warrior获取生命元
for (int i = 0; i < 2; ++i)
if ((Warrior_In_City[i]) and (!Warrior_In_City[1-i])){
Warrior_In_City[i]->Minute_30(Life);
Life = 0; break;
}
}
void Minute_35(City* Cp[]){//处理arrow事件
for (int j = 0; j < 2; ++j)
if (Warrior_In_City[j]) if (Warrior_In_City[j]->weapon_(arrow))
if (Cp[1-j]) if ((Cp[1-j]->Warrior_In_City[1-j])){
Warrior_In_City[j]->arrow_shot();
Cp[1-j]->Warrior_In_City[1-j]->Be_shoted();
}
}
void Minute_38(){//处理bomb事件,顺带处理35分钟时城市中两只warrior均被被射死的情况
if (Warrior_In_City[0] and Warrior_In_City[1]){
bool p =false;
for (int i = 0; i < 2; ++i)
if (Warrior_In_City[i]->weapon_(bomb)){
if (Flag == -1) p = Warrior_In_City[i]->bomb(Warrior_In_City[1-i], Number);
else p = Warrior_In_City[i]->bomb(Warrior_In_City[1-i], Flag+1);
if (p){
delete Warrior_In_City[0]; Warrior_In_City[0] = NULL;
delete Warrior_In_City[1]; Warrior_In_City[1] = NULL;
break;
}
}
if (!p and Warrior_In_City[0]->life() <= 0 and Warrior_In_City[1]->life() <= 0){
delete Warrior_In_City[0]; Warrior_In_City[0] = NULL;
delete Warrior_In_City[1]; Warrior_In_City[1] = NULL;
}
}
}
void Battle(){//战斗及输出,不进行生命元奖励、获取处理
if (Warrior_In_City[0] and Warrior_In_City[1]){
if (Flag == -1){
if (Number % 2) Warrior_In_City[0]->Fight(Warrior_In_City[1]);
else Warrior_In_City[1]->Fight(Warrior_In_City[0]);
}else
Warrior_In_City[Flag]->Fight(Warrior_In_City[1-Flag]);
}
}
void Flag_Set(int i){//战斗后旗帜设置
if (i == -1){Flag_G[0] = 0; Flag_G[1] = 0;}
else{
++Flag_G[i]; Flag_G[1-i] = 0;
if (Flag_G[i] == 2 and Flag != i){
Flag = i;
Print_time();
cout << Color[i] << " flag raised in city " << Number << endl;}
}
}
void Reward(int i){if(Warrior_In_City[i]) Warrior_In_City[i]->Reward();}
void Warrior_report(int i){if(Warrior_In_City[i]) Warrior_In_City[i]->Report_weapon();}
void Win_get(){//奖励获胜士兵生命元
for (int i = 0; i < 2; ++i)
if (Warrior_In_City[i]){
if (Warrior_In_City[i]->IF_win()){
Warrior_In_City[i]->ADD(Life);
Life = 0; Warrior_In_City[i]->IF_win() = false;
}else if (Warrior_In_City[i]->life() <=0){
delete Warrior_In_City[i];
Warrior_In_City[i] = NULL;
}
}
}
};
class Command{
private:
int Total_Life, Knights_Num, Colour, Enemy_Enter;//生命元,造士兵数量,command颜色,有多少敌人进入
bool Weather_Enter;//是否有敌人进入
Warrior* Enemys[2];//进入的敌人
Warrior* Knight;//warrior
public:
int colour(){return Colour;}
string colour(bool p){return p? Color[Colour]: Color[1-Colour];}
Command(int TLife, int col){
Total_Life = TLife;Colour = col;
Knights_Num = 0;
Knight = NULL; Enemy_Enter = 0;
Weather_Enter = false;
Enemys[0] = NULL; Enemys[1] = NULL;
}
void Minute_0(){//制造warrior及输出
if (Total_Life >= Life_Make[Order[Colour][Knights_Num % 5]]){
Total_Life -= Life_Make[Order[Colour][Knights_Num % 5]];
Print_time();
cout << Color[Colour] << ' ';
Knight = new Warrior(Knights_Num+1, Order[Colour][Knights_Num % 5], Life_Make[Order[Colour][Knights_Num% 5]], Total_Life, this);
Knights_Num++;
}
}
void Minute_5(){//处理逃跑lion
if (Knight) if (Knight->Minute_5()){delete Knight; Knight = NULL;}
}
void Move(City* Cp, int i){Cp->Move(Knight, i); Knight = NULL;}//warrior走出command
void Enemy_Move_In(Warrior* enemy){//敌方warrior进入
Enemys[Enemy_Enter] = enemy;
Weather_Enter = true;
++Enemy_Enter;
}
void Minute_10(){//敌方warrior进入输出
if (Weather_Enter){
Enemys[Enemy_Enter-1]->Minute_10(true);
Weather_Enter = false;
}
}
bool If_occupied(){//command是否被占领
if (Enemy_Enter == 2){
Print_time();
cout << Color[Colour] << " headquarter was taken\n";
return true;
}
return false;
}
void Minute_30(int Add_life){Total_Life += Add_life;}
int &Life(){return Total_Life;}
void Report_life(){//command报告生命元
Print_time();
cout << Total_Life << " elements in " << Color[Colour] << " headquarter\n";
}
void Report(){if (Enemy_Enter) Enemys[Enemy_Enter-1]->Report_weapon();}//已进入command的warrior仍要report
~Command(){
if (Knight) delete Knight;
if (Enemys[0]) delete Enemys[0];
if (Enemys[1]) delete Enemys[1];
}
};
void Game_Start(){
int times = 0;
cin >> times;
for (int t = 0; t < times; ++t){
int M, N;//初始command生命元,城市数量
cin >> M >> N >> arrow_attack >> Loyal_reduce >> Total_Minutes;
Command COM[2] = {Command(M,0),Command(M,1)};
vector Citys;
for (int i = 0; i < N; ++i){
City temp(i + 1);
Citys.push_back(temp);
}
for (int i = 0; i < 5; ++i)
cin >> Life_Make[i];
for (int i = 0; i < 5; ++i)
cin >> Attack_[i];
cout << "Case " << t + 1 << ":\n";
Hour = 0; Minute = 0;//计时开始
while(Hour * 60 <= Total_Minutes){
COM[0].Minute_0(); COM[1].Minute_0(); Minute = 5;//第0分钟
if (Hour * 60 + Minute > Total_Minutes) break;//第5分钟
else {
COM[0].Minute_5();
for (vector::iterator i = Citys.begin(); i != Citys.end(); ++i)
(*i).Minute_5();
COM[1].Minute_5();
Minute = 10;
}
if (Hour * 60 + Minute > Total_Minutes) break;//第10分钟
else {
if (Citys[0].If_exist(1)) Citys[0].Move(&COM[0], 1);//warrior前进
for (int i = 0; i < N - 1; ++i)
Citys[i].Move(&Citys[i+1], 1);
COM[1].Move(&Citys[N - 1], 1);
if (Citys[N-1].If_exist(0)) Citys[N-1].Move(&COM[1], 0);
for (int i = N - 1; i > 0; --i)
Citys[i].Move(&Citys[i-1], 0);
COM[0].Move(&Citys[0], 0);
COM[0].Minute_10();//warrior移动输出
bool p = COM[0].If_occupied();
for (int i = 0; i < N; ++i) Citys[i].Minute_10();
COM[1].Minute_10();
if (p + COM[1].If_occupied()) break;
}
Minute = 20;
if (Hour * 60 + Minute > Total_Minutes) break;//第20分钟
else
for (int i = 0; i < N; ++i) Citys[i].Add_Life();
Minute = 30;
if (Hour * 60 + Minute > Total_Minutes) break;//第30分钟
else
for (int i = 0; i < N; ++i) Citys[i].Minute_30();
Minute = 35;
if (Hour * 60 + Minute > Total_Minutes) break;//第35分钟
else
if (N > 1){//city数大于1时才会发生arrow事件
City* Cp[2] = {};
Cp[0] = NULL; Cp[1] = &Citys[1];
Citys[0].Minute_35(Cp);
for (int i = 1; i < N-1; ++i){
Cp[0] = &Citys[i-1]; Cp[1] = &Citys[i+1];
Citys[i].Minute_35(Cp);
}
Cp[0] = &Citys[N-2]; Cp[1] = NULL;
Citys[N-1].Minute_35(Cp);
}
Minute = 38;
if (Hour * 60 + Minute > Total_Minutes) break;//第38分钟
else
for (vector::iterator i = Citys.begin(); i != Citys.end(); ++i)
(*i).Minute_38();
Minute = 40;
if (Hour * 60 + Minute > Total_Minutes) break;//第40分钟
else{
for (vector::iterator i = Citys.begin(); i != Citys.end(); ++i)//战斗及输出
(*i).Battle();
for (vector::iterator i = Citys.begin(); i != Citys.end(); ++i)//奖励生命元
(*i).Reward(0);
for (vector::reverse_iterator i = Citys.rbegin(); i != Citys.rend(); ++i)
(*i).Reward(1);
for (vector::iterator i = Citys.begin(); i != Citys.end(); ++i)//获取city生命元
(*i).Win_get();
}
Minute = 50;
if (Hour * 60 + Minute > Total_Minutes) break;//第50分钟
else
COM[0].Report_life();COM[1].Report_life();
Minute = 55;
if (Hour * 60 + Minute > Total_Minutes) break;//第55分钟
else{
for (vector::iterator i = Citys.begin(); i != Citys.end(); ++i)
(*i).Warrior_report(0);
COM[1].Report();COM[0].Report();
for (vector::iterator i = Citys.begin(); i != Citys.end(); ++i)
(*i).Warrior_report(1);
}
Minute = 0;
Hour++;
}
}
}
int main(){
// freopen("d:\\anser.txt", "w", stdout);
Game_Start();
// fclose(stdout);
return 0;
}
bool Warrior::Minute_5(){
if (name == lion) if (Loyal <= 0){
Print_time();
cout << Command_Belong_to->colour(true) << " lion " << Num << " ran away\n";
return true;
}
return false;
}
void Warrior::Minute_10(bool If_arrive){
++Step;
if (name == iceman and !(Step % 2)){
if (Life < 10) Life = 1;
else Life -= 9;
Attack += 20;
}
Print_time();
cout << Command_Belong_to->colour(true) << ' ' << Knight[name] << ' ' << Num;
if (If_arrive)
cout << " reached " << Command_Belong_to->colour(false) << " headquarter";
else cout << " marched to city " << City_Belong_to->Num();
cout << " with " << Life << " elements and force " << Attack << endl;
}
void Warrior::Minute_30(int Add_life){
Print_time();
cout << Command_Belong_to->colour(true) << ' ' << Knight[name] << ' ' << Num << " earned " << Add_life << " elements for his headquarter\n";
Command_Belong_to->Minute_30(Add_life);
}
void Warrior::arrow_shot(){
Print_time();
cout << Command_Belong_to->colour(true) << ' ' << Knight[name] << ' ' << Num << " shot";
weapon[arrow]->usetime()--;
if(!weapon[arrow]->usetime()){delete weapon[arrow]; weapon[arrow] = NULL;}
}
void Warrior::Be_shoted(){
Life -= arrow_attack;
if (Life <= 0){cout << " and killed " << Command_Belong_to->colour(true) << ' ' << Knight[name] << ' ' << Num;}
cout << endl;
}
void City::Move(Command *Cp, int i){
Cp->Enemy_Move_In(Warrior_In_City[i]);
Warrior_In_City[i] = NULL;
}
void Warrior::Use_bomb(Warrior *Wp){
Print_time();
cout << Command_Belong_to->colour(true) << ' ' << Knight[name] << ' ' << Num << " used a bomb and killed " << (Wp->Command_Belong_to)->colour(true) << ' ' << Knight[Wp->name] << ' ' << Wp->Num << endl;
}
bool Warrior::bomb(Warrior *Wp, int p){
if ((p + Command_Belong_to->colour()) % 2){
if (fight(Wp) == -1) {Use_bomb(Wp); return true;}
}else
if (Wp->fight(this) == 1) {Use_bomb(Wp); return true;}
return false;
}
void Warrior::Dead(){
Print_time();
cout << Command_Belong_to->colour(true) << ' ' << Knight[name] << ' ' << Num << " was killed in city " << City_Belong_to->Num() << endl;
}
void Warrior::Fight(Warrior *Wp){
Warrior *Wp_win = NULL; Warrior *Wp_lose = NULL;
l_life = Life; Wp->l_life = Wp->Life;
if (Life > 0 and (Wp->Life) > 0){
int swatk = 0;
if (weapon[sword]) swatk = weapon[sword]->sw_atk();
Print_time();
cout << Command_Belong_to->colour(true) << ' ' << Knight[name] << ' ' << Num << " attacked " << (Wp->Command_Belong_to)->colour(true) << ' ' << Knight[Wp->name] << ' ' << Wp->Num << " in city " << City_Belong_to->Num() << " with " << Life << " elements and force " << Attack << endl;
Wp->Life = Wp->Life - Attack - swatk;
if (swatk) if (!weapon[sword]->sword_dull()){delete weapon[sword]; weapon[sword] = NULL;}
if (Wp->Life > 0){
if (Wp->name == ninja) {City_Belong_to->Flag_Set(-1);Morale_Change();Loyal_Reduce();}
else{
int E_swatk = 0;
if (Wp->weapon[sword]) E_swatk = (Wp->weapon[sword])->sw_atk();
Print_time();
cout << (Wp->Command_Belong_to)->colour(true) << ' ' << Knight[Wp->name] << ' ' << Wp->Num << " fought back against " << Command_Belong_to->colour(true) << ' ' << Knight[name] << ' ' << Num << " in city " << City_Belong_to->Num() <Attack / 2) - E_swatk;
if (E_swatk) if(!(Wp->weapon[sword])->sword_dull()){delete Wp->weapon[sword]; Wp->weapon[sword] = NULL;}
if (Life > 0) {City_Belong_to->Flag_Set(-1);Morale_Change();Wp->Morale_Change();Loyal_Reduce();Wp->Loyal_Reduce();}
else{Wp->If_kill = true;Wp_lose = this;Wp_win = Wp;}
}
}else{If_kill = true;Wp_win = this;Wp_lose = Wp;}
}else{
if (Life > 0){Wp->l_life = 0;Wp_win = this;Wp_lose = Wp;}
else {l_life = 0;Wp_lose = this;Wp_win = Wp;}
}
if (Wp_win){Wp_win->account(Wp_lose);}
if (name == dragon and Life > 0 and Morale > 0.8){
Print_time();
cout << Command_Belong_to->colour(true) << ' ' << Knight[name] << ' ' << Num << " yelled in city " << City_Belong_to->Num() << endl;
}
if (Wp_win){
Print_time();
cout << (Wp_win->Command_Belong_to)->colour(true) << ' ' << Knight[Wp_win->name] << ' ' << Wp_win->Num << " earned " << City_Belong_to->Life_() << " elements for his headquarter\n";
(Wp_win->City_Belong_to)->Flag_Set((Wp_win->Command_Belong_to)->colour());
}
}
void Warrior::Reward(){
if (If_win)
if (Command_Belong_to->Life() > 7){
Command_Belong_to->Life() -= 8;
Life += 8;
}
}
void Warrior::ADD(int life){Command_Belong_to->Life() += life;}
void Warrior::Report_weapon(){
bool p = false;
Print_time();
cout << Command_Belong_to->colour(true) << ' ' << Knight[name] << ' ' << Num << " has ";
for (int i = 2; i >= 0; --i)
if (weapon[i]){
if (p) cout << ',';else p = true;
cout << Weapons_[i];
if (i == 2) cout << '(' << weapon[arrow]->usetime() << ')';
if (i == 0) cout << '(' << weapon[sword]->sw_atk() << ')';
}
if(!p) cout << "no weapon";
cout << endl;
}
#include
#include
#include
#include
#include
#include
#include
#include
#include
const double EPS = 1e-10;
using namespace std;
enum EEventType { EVENT_BORN, EVENT_LION_RUN,EVENT_MARCH, EVENT_ARROW,EVENT_BOMB,EVENT_ATTACK,
EVENT_FIGHTBACK,EVENT_KILLED, EVENT_YELL, EVENT_EARNMONEY,
EVENT_FLAG, EVENT_REACH,EVENT_CITYTAKEN,EVENT_PRINTMONEY,EVENT_WARRIOR_REPORT };
enum { WEAPON_SWORD,WEAPON_BOMB,WEAPON_ARROW };
enum { DRAGON,NINJA,ICEMAN,LION,WOLF};
#define WEAPON_NUM 3
#define WARRIOR_NUM 5
class CWeapon
{
public:
int nKindNo;
int nForce;
static const char * Names[WEAPON_NUM];
static int nArrowForce;
bool operator<( const CWeapon & w) const
{
return w.nKindNo < nKindNo;
}
};
#define COLOR_RED 0
#define COLOR_BLUE 1
#define COLOR_NONE 3
class CHeadquarter;
class CKingdom;
class CWarrior;
class CCity;
class CWeapon;
typedef CWarrior* PWARRIOR;
string MyIntToStr( int n)
{
char szTmp[300];
sprintf(szTmp,"%d",n);
return szTmp;
}
//cls CWarrior
class CWarrior
{
friend class CHeadquarter;
friend bool MyCompare(const PWARRIOR & p1, const PWARRIOR & p2);
protected:
int nStrength;
int nForce;
int nCityNo;
int nId;
bool bShotToDeath;
CHeadquarter * pHeadquarter;
public:
static int InitalForce [WARRIOR_NUM];
static const char * Names[WARRIOR_NUM];
static int InitialLifeValue [WARRIOR_NUM];
virtual bool Runaway() { return false; }
virtual bool HasBomb() { return false; }
virtual int GetSwordForce() { return 0;}
virtual int UseSword() { return 0;}
virtual void AddMorale(double a) { };
virtual void EarnWeapons( CWarrior * pEnemy) { }
virtual string ReportWeapons() { return "";}
// virtual void PrintResult(int nTime,int nKindNo);
// virtual void PrintResult(int nTime) = 0;
bool virtual VirtualAttack( CWarrior * pEnemy);
bool virtual VirtualFightback( CWarrior * pEnemy);
virtual ~CWarrior() { }
virtual int Attack( CWarrior * pEnemy);
virtual int HurtedBy(CWarrior * pEnemy);
virtual string GetName() = 0;
virtual void Killed();
virtual void March();
int AttackedByArrow( int nArrowForce) {
nStrength -= nArrowForce;
if( nStrength <= 0 ) {
nStrength = 0;
bShotToDeath = true;
}
return nStrength;
}
virtual int ShootArrow() { return 0; } //返回箭的攻击力
string GetColorStr();
int GetColor() const;
CWarrior(int nId_,int nStrength_,int nForce_,int nCityNo_, CHeadquarter * pHeadquarter_):
nId(nId_),nStrength(nStrength_),nForce(nForce_),nCityNo(nCityNo_),pHeadquarter(pHeadquarter_),
bShotToDeath(false)
{
}
int GetStrength( )
{
return nStrength;
}
int GetForce()
{
return nForce;
}
void SetStrength(int n)
{
nStrength = n;
}
void SetForce(int n)
{
nForce = n;
}
int GetPosition()
{
return nCityNo;
}
virtual void FightBack(CWarrior * pEnemy) {
int nSwordForce = UseSword();
pEnemy->nStrength -= nForce/2 + nSwordForce;
}
};
class CWeaponWarrior:public CWarrior
{
public:
vector vwp;
public:
CWeaponWarrior(int nId_, int nStrength_,int nForce_,int nCityNo_,
CHeadquarter * pHeadquarter_,int nWeaponNum ):
CWarrior(nId_,nStrength_,nForce_,nCityNo_,pHeadquarter_),vwp(nWeaponNum)
{ }
bool HasBomb() {
for(int i = 0; i < vwp.size();i ++)
if( vwp[i].nKindNo == WEAPON_BOMB)
return true;
return false;
}
int GetSwordForce() {
for(int i = 0; i < vwp.size();i ++)
if( vwp[i].nKindNo == WEAPON_SWORD)
return vwp[i].nForce;
return 0;
}
int UseSword() {
for(int i = 0; i < vwp.size();i ++)
if( vwp[i].nKindNo == WEAPON_SWORD) {
int nTmp = vwp[i].nForce;
vwp[i].nForce *= 0.8;
if( vwp[i].nForce == 0)
vwp.erase ( vwp.begin () + i);
return nTmp;
}
return 0;
}
int ShootArrow()
{
for(vector::iterator i = vwp.begin(); i != vwp.end();i ++)
if( i->nKindNo == WEAPON_ARROW) {
i->nForce --;
if( i->nForce == 0)
vwp.erase(i);
return CWeapon::nArrowForce;
}
return 0;
}
string ReportWeapons()
{
if( vwp.size() == 0)
return "";
string rs = " has ";
sort(vwp.begin(),vwp.end());
bool bFirst = true;
for( int i = 0;i < vwp.size();i ++ ) {
if( ! bFirst )
rs += ",";
else
bFirst = false;
rs += CWeapon::Names[vwp[i].nKindNo];
if( vwp[i].nKindNo != WEAPON_BOMB )
rs += string("(") + MyIntToStr(vwp[i].nForce)+ ")";
}
return rs;
}
};
class CNinja:public CWeaponWarrior
{
friend class CHeadquarter;
public:
//CNinja constructor
CNinja(int nId_,int nStrength_,int nForce_,int nCityNo_, CHeadquarter * pHeadquarter_):
CWeaponWarrior(nId_,nStrength_,nForce_,nCityNo_,pHeadquarter_,2)
{
bool bDeleteSword = false;
vector::iterator p;
for( int i = 0;i < 2;i ++) {
vwp[i].nKindNo =( nId_ + i )% WEAPON_NUM;
if( vwp[i].nKindNo == WEAPON_SWORD ) {
vwp[i].nForce = nForce_ * 0.2;
if(vwp[i].nForce == 0) {
bDeleteSword = true;
p = vwp.begin() + i;
}
}
else if( vwp[i].nKindNo == WEAPON_ARROW )
vwp[i].nForce = 3;
}
if( bDeleteSword)
vwp.erase (p);
}
virtual int HurtedBy(CWarrior * pEnemy);
virtual string GetName();
bool VirtualFightback( CWarrior * pEnemy) { return false; }
};
class CDragon:public CWeaponWarrior
{
friend class CHeadquarter;
private:
double fMorale;
public:
CDragon(int nId_,int nStrength_,int nForce_,int nCityNo_, CHeadquarter * pHeadquarter_);
virtual int Attack( CWarrior * p) ;
void FightBack(CWarrior * pEnemy);
virtual string GetName();
void AddMorale(double a) { fMorale += a; };
};
class CLion:public CWarrior
{
friend class CHeadquarter;
private:
int nLoyalty;
public:
static int nLoyaltyDec;
CLion(int nId_,int nStrength_,int nForce_,int nCityNo_, CHeadquarter * pHeadquarter_);
int HurtedBy(CWarrior * pEnemy);
void FightBack(CWarrior * pEnemy);
int Attack( CWarrior * p) ;
virtual string GetName();
bool Runaway () { return nLoyalty <= 0; }
};
class CIceman:public CWeaponWarrior
{
friend class CHeadquarter;
private:
int nSteps;
public:
//CIceman constructor
CIceman(int nId_,int nStrength_,int nForce_,int nCityNo_, CHeadquarter * pHeadquarter_):
CWeaponWarrior(nId_,nStrength_,nForce_,nCityNo_,pHeadquarter_,1),nSteps(0)
{
vwp[0].nKindNo = nId % WEAPON_NUM;
if( vwp[0].nKindNo == WEAPON_SWORD ) {
vwp[0].nForce = nForce_ * 0.2;
if( vwp[0].nForce == 0)
vwp.clear();
}
else if( vwp[0].nKindNo == WEAPON_ARROW )
vwp[0].nForce = 3;
}
virtual void March() ;
virtual string GetName() ;
};
class CWolf:public CWeaponWarrior
{
friend class CHeadquarter;
private:
int nEnemyKilled;
public:
//CWolf Constructor
CWolf(int nId_,int nStrength_,int nForce_,int nCityNo_, CHeadquarter * pHeadquarter_):
CWeaponWarrior(nId_,nStrength_,nForce_,nCityNo_,pHeadquarter_,0), nEnemyKilled(0)
{
}
virtual int Attack( CWarrior * pEnemy);
virtual string GetName() ;
void EarnWeapons( CWarrior * pEnemy) ;
};
//cls CHeadQuarter
class CHeadquarter {
friend class CWarrior;
friend class CWolf;
friend class CDragon;
friend class CIceman;
friend class CLion;
friend class CNinja;
private:
int nBloodMoney ; // 纪录打仗赢后得到的
int nMoney;
int nEnemys;
int nWarriorNo;
list lstWarrior;
int nColor;
CKingdom * pKingdom;
int nCityNo; //red: 0 ,blue nCitynum + 1
CHeadquarter * pEnemyheadquarter;
vector vAwardList;
public:
static int MakingSeq[2][WARRIOR_NUM];
CHeadquarter(int nColor_, int nMoney_,int nCityNo_ ) : nColor(nColor_), nWarriorNo(1),
nEnemys(0),nMoney(nMoney_),nCityNo(nCityNo_),nBloodMoney(0)
{
}
~CHeadquarter()
{
list ::iterator p;
for( p = lstWarrior.begin(); p != lstWarrior.end(); p ++ )
delete (* p);
lstWarrior.clear();
}
void SetEnemy( CHeadquarter * p)
{
pEnemyheadquarter = p;
}
void SetKingdom( CKingdom * p)
{
pKingdom = p;
}
void AddEvent( EEventType eType, int nCityNo, int nColor,const string & sEventString);
void PrintMoney();
string GetColorStr()
{
if( nColor == COLOR_RED)
return "red";
else
return "blue";
}
int GetColor()
{
return nColor;
}
void LionRunaway();
void Bomb();
void ShootArrow();
void WarriorBorn();
void AddToAwardList( CWarrior * pWarrior);
void GiveAward();
void WarriorsMarch(int nEnemyHeadquterCityNo );
void WarriorsAttack();
void WarriorsReport();
void EnemyReach();
void WarriorsGetFreeMoney(int);
CWarrior * QueryCityWarrior( int nCityNo);
void EarnBloodMoney( CWarrior * p, int nCityNo);
//addfor 2010
void AddBloodMoney() {
nMoney += nBloodMoney;
nBloodMoney = 0;
}
//gwend
};
class CCity
{
private:
int nFlagColor;
int nNo;
int nLastWinWarriorColor;
public:
int nMoney;
CCity( ):nFlagColor(COLOR_NONE),nMoney(0),nLastWinWarriorColor(COLOR_NONE)
{
}
//modifor 2010
bool CWarriorWin( int nColor) //返回是否要升旗子
{
if( nColor == nLastWinWarriorColor ) {
if( nFlagColor != nColor) {
SetFlagColor(nColor);
return true;
}
else
return false;
}
nLastWinWarriorColor = nColor;
return false;
}
void WarDraw()
{
nLastWinWarriorColor = COLOR_NONE;
}
void SetNo(int nNo_ )
{
nNo = nNo_;
}
//void Earthquake();
void AddMoney() {
nMoney += 10;
}
int MoneyTaken() {
int nTmp = nMoney;
nMoney = 0;
return nTmp;
}
void SetFlagColor( int nColor)
{
nFlagColor = nColor;
}
int GetFlagColor()
{
return nFlagColor;
}
int GetTotalMoney()
{
return nMoney;
}
};
class CEvent
{
private:
EEventType eEventType;
int nTime;
int nCityNo;
int nColor;
string sDescribe;
public:
CEvent(EEventType eEventType_,int nTime_,int nCityNo_,int nColor_, const string & s) :
eEventType(eEventType_),nTime(nTime_),nCityNo(nCityNo_),nColor(nColor_),sDescribe(s)
{
}
void Output()
{
char szTime[20];
sprintf(szTime,"%03d:%02d",nTime /60, nTime % 60);
cout << szTime << " " << sDescribe << endl;
}
bool operator < ( const CEvent & e2 ) const {
if( nTime < e2.nTime )
return true;
else if( nTime > e2.nTime )
return false;
if( eEventType == e2.eEventType && eEventType == EVENT_WARRIOR_REPORT) {
if( nColor < e2.nColor )
return true;
else if( nColor == e2.nColor)
return nCityNo < e2.nCityNo ;
else
return false;
}
if( nCityNo < e2.nCityNo )
return true;
else if( nCityNo > e2.nCityNo )
return false;
if( eEventType < e2.eEventType )
return true;
else if( eEventType > e2.eEventType )
return false;
if( nColor < e2.nColor )
return true;
else
return false;
}
};
class CKingdom
{
friend class CHeadquarter;
private:
CHeadquarter Red, Blue;
int nTimeInMinutes;
vector vEvent;
vector vCity;
int nEndTime;
int nCityNum;
public:
void Run(int T) {
for( int t = 0; t <= T; t ++ ) { //modifor 2010 old: t < T
if( TimePass(t) == 0)
return ;
}
}
CKingdom(int nCityNum_,int nInitMoney):
nTimeInMinutes(0),Red(COLOR_RED,nInitMoney,0),Blue(COLOR_BLUE,nInitMoney,nCityNum_ + 1),
nCityNum(nCityNum_), vCity(nCityNum_ + 1)
{
for( int i = 1; i <= nCityNum;i ++ )
vCity[i].SetNo(i);
Red.SetKingdom(this);
Red.SetEnemy( &Blue);
Blue.SetKingdom(this);
Blue.SetEnemy( &Red);
nEndTime = 3000000;
}
int TimePass(int nMinutes) ;
string SysemTimeStr()
{
char szTime[20];
sprintf(szTime,"%03d:%02d",nTimeInMinutes /60, nTimeInMinutes % 60);
return szTime;
}
void WarDraw( int nCityNo)
{
vCity[nCityNo].WarDraw();
}
void KWarriorWin( CWarrior * pWarrior)
{
int nCityNo = pWarrior->GetPosition();
if( vCity[nCityNo].CWarriorWin( pWarrior->GetColor()) == true ) {
//addfor 2010 要判断是否已经有同颜色的旗子,有则不升旗
string sEventString = pWarrior->GetColorStr() + " flag raised in city " + MyIntToStr( nCityNo);
AddEvent(EVENT_FLAG, nCityNo, pWarrior->GetColor(),sEventString);
}
}
int GetTime()
{
return nTimeInMinutes;
}
void WarEnd()
{
if( nEndTime == 3000000)
nEndTime = nTimeInMinutes;
}
void OutputResult()
{
sort(vEvent.begin(),vEvent.end());
for( int i = 0;i < vEvent.size();i ++ )
vEvent[i].Output();
}
void AddEvent( EEventType eType, int nCityNo, int nColor, const string & sEventString);
//void CityEarthQuake( int nNo);
int GetCityFlagColor( int nCityNo)
{
return vCity[nCityNo].GetFlagColor();
}
int QueryCityMoney( int nNo)
{
return vCity[nNo].GetTotalMoney();
}
void TakeCityMoney( int nNo)
{
vCity[nNo].MoneyTaken();
}
};
//CWarrior functions
int CWarrior::GetColor() const
{
return pHeadquarter->GetColor();
}
string CWarrior::GetColorStr()
{
return pHeadquarter->GetColorStr();
}
bool CWarrior::VirtualFightback( CWarrior * pEnemy)
//假定能够开始反击
{
if(nStrength > 0 && nForce /2 + GetSwordForce() >= pEnemy->nStrength )
return true; //反击敌人致死
return false;
}
bool CWarrior::VirtualAttack( CWarrior * pEnemy)
{
if( nStrength > 0 && nForce + GetSwordForce() >= pEnemy->nStrength )
return true; //杀死敌人
return false;
}
int CWarrior::Attack( CWarrior * pEnemy)
{
if( pEnemy->GetStrength() <= 0) //敌人已经被箭射杀了
return 1;
char szTmp[200];
sprintf(szTmp," with %d elements and force %d",nStrength,nForce);
string sEventString = GetName() + " attacked " +
pEnemy->GetName() + string(" in city ") + MyIntToStr(nCityNo) + szTmp;// modifor 2010
pHeadquarter->AddEvent( EVENT_ATTACK, nCityNo, GetColor(), sEventString);
if( pEnemy->HurtedBy(this) <= 0) {
return 1; //杀死敌人
}
if( nStrength <= 0 ) {
Killed();
return -1; //被反击的敌人杀死
}
return 0;
}
int CWarrior::HurtedBy(CWarrior * pEnemy)
{
int nSwordForce = pEnemy->UseSword();
nStrength -= pEnemy->GetForce() + nSwordForce;
if( nStrength <= 0 ) {
Killed();
return -1;
}
else {
string sEventString = GetName() + " fought back against " + pEnemy->GetName() + " in city " + MyIntToStr(nCityNo);
FightBack(pEnemy);
pHeadquarter->AddEvent(EVENT_FIGHTBACK,nCityNo, GetColor(),sEventString);
return nStrength;
}
}
void CWarrior::Killed()
{
string sEventString = GetName() + " was killed in city " + MyIntToStr(nCityNo);
pHeadquarter->AddEvent(EVENT_KILLED, nCityNo, GetColor(), sEventString);
}
void CWarrior::March()
{
if( GetColor() == COLOR_RED)
nCityNo ++;
else
nCityNo --;
}
int CNinja::HurtedBy(CWarrior * pEnemy)
{
int nSwordForce = pEnemy->UseSword();
nStrength -= pEnemy->GetForce() + nSwordForce;
if( nStrength <= 0 ) {
Killed();
return -1;
}
return nStrength;
}
string CNinja::GetName()
{
return pHeadquarter->GetColorStr() + " ninja " + MyIntToStr(nId);
}
//CDragon Constructor
CDragon::CDragon(int nId_,int nStrength_,int nForce_,int nCityNo_, CHeadquarter * pHeadquarter_):
CWeaponWarrior(nId_,nStrength_,nForce_,nCityNo_,pHeadquarter_,1)
{
vwp[0].nKindNo = nId_ % WEAPON_NUM;
if( vwp[0].nKindNo == WEAPON_SWORD ) {
vwp[0].nForce = nForce_ * 0.2;
if( vwp[0].nForce == 0)
vwp.clear();
}
else if( vwp[0].nKindNo == WEAPON_ARROW )
vwp[0].nForce = 3;
fMorale = pHeadquarter -> nMoney /(double)CWarrior::InitialLifeValue [0];
}
int CDragon::Attack( CWarrior * p)
{
int nRetVal = CWarrior::Attack(p);
if( nRetVal != -1 && fMorale > 0.8) { //没有战死
string sEventString = GetName() + " yelled in city " + MyIntToStr(nCityNo);
pHeadquarter->AddEvent( EVENT_YELL, nCityNo, GetColor(), sEventString);
if( nRetVal == 0) //平局
fMorale -= 0.2;
else
fMorale += 0.2;
}
return nRetVal;
}
void CDragon::FightBack(CWarrior * pEnemy)
{
CWarrior::FightBack (pEnemy);
if( pEnemy->GetStrength() > 0 )
fMorale -= 0.2;
else
fMorale += 0.2;
}
string CDragon::GetName()
{
return pHeadquarter->GetColorStr() + " dragon " + MyIntToStr(nId);
}
//CLion Constructor
CLion::CLion(int nId_,int nStrength_,int nForce_,int nCityNo_, CHeadquarter * pHeadquarter_):
CWarrior(nId_,nStrength_,nForce_,nCityNo_,pHeadquarter_)
{
nLoyalty = pHeadquarter ->nMoney;
}
int CLion::Attack( CWarrior * p)
{
int nTmp = nStrength;
int nRetVal = CWarrior::Attack(p);
if( nRetVal == -1) //被敌人反击杀死
p->SetStrength (p->GetStrength () + nTmp);
else if( nRetVal != 1 ) //未能杀死敌人
nLoyalty -= CLion::nLoyaltyDec ;
return nRetVal;
}
void CLion::FightBack(CWarrior * pEnemy)
{
CWarrior::FightBack (pEnemy);
if( pEnemy->GetStrength() > 0 )
nLoyalty -= CLion::nLoyaltyDec ;
}
int CLion::HurtedBy(CWarrior * pEnemy)
//此处实现生命向敌人转移
{
int nSwordForce = pEnemy->UseSword();
if( nStrength - pEnemy->GetForce() - nSwordForce <= 0 ) {
pEnemy->SetStrength( pEnemy->GetStrength() + nStrength );
nStrength = 0;
Killed();
return -1;
}
nStrength -= pEnemy->GetForce() + nSwordForce;
string sEventString = GetName() + " fought back against " + pEnemy->GetName() + " in city " + MyIntToStr(nCityNo);
FightBack(pEnemy);
pHeadquarter->AddEvent(EVENT_FIGHTBACK,nCityNo, GetColor(),sEventString);
return nStrength;
}
string CLion::GetName()
{
return pHeadquarter->GetColorStr() + " lion " + MyIntToStr(nId);
}
void CIceman::March()
{
CWarrior::March();
nSteps = ( nSteps + 1 ) %2;
if( nSteps == 0) {
if( nStrength - 9 > 1 )
nStrength -= 9;
else
nStrength = 1;
nForce += 20;
}
}
string CIceman::GetName()
{
return pHeadquarter->GetColorStr() + " iceman " + MyIntToStr(nId);
}
void CWolf::EarnWeapons( CWarrior * pEnemy)
{
int i,j;
if( pEnemy->ReportWeapons() != "") {
CWeaponWarrior * p = ( CWeaponWarrior *) pEnemy;
for(i = 0;i < p->vwp.size(); i ++ ) {
bool bAlreadyHas = false;
for( j = 0; j < vwp.size(); j ++ ) {
if( p->vwp[i].nKindNo == vwp[j].nKindNo ) {
bAlreadyHas = true;
break;
}
}
if( ! bAlreadyHas)
vwp.push_back ( p->vwp[i]);
}
}
}
int CWolf::Attack( CWarrior * pEnemy)
{
int nEnemyStrength = pEnemy->GetStrength();
int nOriStrength = nStrength;
int nRetVal = CWarrior::Attack(pEnemy);
if( nRetVal > 0 ) //杀死敌人
EarnWeapons( pEnemy);
return nRetVal;
}
string CWolf::GetName()
{
return pHeadquarter->GetColorStr() + " wolf " + MyIntToStr(nId);
}
//CHeadquarter functions
void CHeadquarter::LionRunaway()
{
string sEventString;
list::iterator i = lstWarrior.begin();
while(i != lstWarrior.end() ) {
if( (*i)->Runaway()) {
//输出样例: 000:05 blue lion 1 ran away
int nCityNo = ( * i )->GetPosition();
if( nColor == COLOR_RED && nCityNo == pKingdom->nCityNum + 1 ||
nColor == COLOR_BLUE && nCityNo == 0 )
continue;
sEventString = (*i)->GetName() + " ran away";
AddEvent( EVENT_LION_RUN, ( * i )-> nCityNo, nColor,sEventString);
i = lstWarrior.erase (i); //指向被erased的元素的后一个
continue;
}
i ++;
}
}
void CHeadquarter::Bomb()
{
list::iterator i = lstWarrior.begin();
while( i != lstWarrior.end() ) {
int nCityNo = ( * i )->GetPosition();
if( (*i)->GetStrength () > 0 ) {
CWarrior * p = pEnemyheadquarter->QueryCityWarrior(nCityNo);
if( p ) {
bool bShouldAttack = false;
if( pKingdom->GetCityFlagColor(nCityNo) == nColor )
bShouldAttack = true;
else if( pKingdom->GetCityFlagColor(nCityNo) == COLOR_NONE) {
if( nColor == COLOR_RED && (nCityNo % 2 == 1))
bShouldAttack = true;
if( nColor == COLOR_BLUE && (nCityNo % 2 == 0))
bShouldAttack = true;
}
bool r1 = false ,r2 = false;
if( ( * i )->HasBomb()) {
if( bShouldAttack) {
if( (*i)->VirtualAttack(p) == false)
r1 = p->VirtualFightback(*i);
else
r1 = false;
}
else
r2 = p->VirtualAttack(*i);
if( r1 || r2 ) { //会被敌人反击杀死或被敌人主动攻击杀死
//输出样例: 000:38 blue dragon 1 used a bomb and killed red lion 7
//string sEventString = (*i)->GetName() + " used a bomb and killed " +
// p->GetName() + string(" in city ") + MyIntToStr(nCityNo);
string sEventString = (*i)->GetName() + " used a bomb and killed " +
p->GetName();
AddEvent( EVENT_BOMB, nCityNo, GetColor(), sEventString);
i = lstWarrior.erase (i); //指向被erased的元素的后一个
p->SetStrength(0);
continue;
}
}
}
}
i ++;
}
}
void CHeadquarter::ShootArrow()
{
list::iterator i;
for( i = lstWarrior.begin();i != lstWarrior.end();i ++ ) {
int nCityNo = ( * i )->GetPosition();
if( nColor == COLOR_RED ) {
nCityNo ++;
if( nCityNo == pKingdom->nCityNum + 1 )
continue ;
}
else {
nCityNo --;
if( nCityNo == 0)
continue;
}
CWarrior * p = pEnemyheadquarter->QueryCityWarrior(nCityNo);
if( p ) {
int nArrowForce = (*i)->ShootArrow();
if( nArrowForce > 0) {
string sEventString = (*i)->GetName() + " shot";
//输出样例: 000:38 blue dragon 1 used a bomb and killed red lion 7
if( p->AttackedByArrow(nArrowForce) <= 0 )
//sEventString += " and killed " + p->GetName() + string(" in city ") + MyIntToStr(nCityNo);
sEventString += " and killed " + p->GetName();
AddEvent( EVENT_ARROW,( * i )->GetPosition(), GetColor(), sEventString);
}
}
}
}
int CKingdom::TimePass(int nMinutes) {
int i;
nTimeInMinutes = nMinutes;
if( nTimeInMinutes > nEndTime )
return 0;
int nRemain = nTimeInMinutes % 60;
switch( nRemain) {
case 0: //生产怪物
Red.WarriorBorn();
Blue.WarriorBorn();
break;
case 5: //lion可能逃跑
Red.LionRunaway();
Blue.LionRunaway();
break;
case 10: //前进
Red.WarriorsMarch(nCityNum + 1);
Blue.WarriorsMarch(0);
break;
case 20: //城市出产生命元
for( i = 0;i < vCity.size();i ++ ) {
vCity[i].AddMoney();
}
break;
case 30: //挣钱
Red.WarriorsGetFreeMoney(nCityNum+1);
Blue.WarriorsGetFreeMoney(nCityNum+1);
break;
case 35: //放箭
Red.ShootArrow();
Blue.ShootArrow();
break;
case 38:
Red.Bomb();
Blue.Bomb();
break;
case 40://发生战斗
//addfor debug cccc
if( nTimeInMinutes == 1720 )
cout << "" ;
//gwend
Red.WarriorsAttack();
Blue.WarriorsAttack();
Red.GiveAward();
Blue.GiveAward();
Red.AddBloodMoney();
Blue.AddBloodMoney();
break;
case 50:
Red.PrintMoney(); //addfor 2010
Blue.PrintMoney(); //addfor 2010
break;
case 55:
Red.WarriorsReport();
Blue.WarriorsReport();
}
return 1;
}
void CHeadquarter::EnemyReach()
{
nEnemys ++;
if( nEnemys == 2 ) {
if( nColor == COLOR_RED )
AddEvent( EVENT_CITYTAKEN, nCityNo, nColor,string("red headquarter was taken"));
else
AddEvent( EVENT_CITYTAKEN, nCityNo, nColor,string("blue headquarter was taken"));
pKingdom->WarEnd();
}
}
CWarrior * CHeadquarter::QueryCityWarrior( int nCityNo)
{
list::iterator i;
for( i = lstWarrior.begin();i != lstWarrior.end();i ++ ) {
if( (* i )->GetPosition () == nCityNo)
return ( * i );
}
return NULL;
}
void CHeadquarter::WarriorsGetFreeMoney(int nEnemyheadquarterNo )
//武士拿城市里的钱,在没有发生战斗的情况下
{
list::iterator i;
for( i = lstWarrior.begin(); i != lstWarrior.end();i ++ ) {
int nCityno = ( * i )->GetPosition();
if( nCityno != 0 && nCityno != nEnemyheadquarterNo) {
CWarrior * p ;
p = pEnemyheadquarter->QueryCityWarrior(nCityno);
if( p == NULL ) {
int nMoneyEarned;
nMoneyEarned = pKingdom->QueryCityMoney(nCityno);
if( nMoneyEarned > 0 ) {
nMoney += nMoneyEarned;
pKingdom->TakeCityMoney(nCityno);
string sEventString = (*i)->GetName() + " earned " + MyIntToStr(nMoneyEarned) + " elements for his headquarter";
AddEvent( EVENT_EARNMONEY, nCityno,nColor, sEventString);
}
}
}
}
}
void CHeadquarter::WarriorsMarch(int nEnemyHeadquterCityNo)
{
list::iterator i;
string sEventString;
for( i = lstWarrior.begin();i != lstWarrior.end();i ++ ) {
int nOldPos = ( * i ) ->nCityNo ;
if( nColor == COLOR_RED ) {
if( ( * i )-> nCityNo < nEnemyHeadquterCityNo)
( *i )->March();
}
else {
if( ( * i )-> nCityNo > nEnemyHeadquterCityNo)
( *i )->March();
}
char szTmp[100];
sprintf( szTmp," with %d elements and force %d",(*i)->nStrength,(*i)->nForce);
if( nOldPos != nEnemyHeadquterCityNo) {
if (( * i )-> nCityNo == nEnemyHeadquterCityNo ) {
sEventString = (*i)->GetName() + " reached "+ pEnemyheadquarter->GetColorStr() + " headquarter" + szTmp;
AddEvent( EVENT_REACH, ( * i )-> nCityNo, nColor,sEventString);
pEnemyheadquarter->EnemyReach();
}
else {
sEventString = (*i)->GetName() + " marched to city " + MyIntToStr(( * i )->GetPosition() ) + szTmp;
AddEvent( EVENT_MARCH, ( * i )->GetPosition(), nColor,sEventString);
}
}
}
}
void CHeadquarter::WarriorsReport()
{
list::iterator i = lstWarrior.begin();
string sEventString;
while(i != lstWarrior.end()) {
if( (*i)->nStrength <= 0) { //在35分,或刚才的战斗中已经被杀了
i = lstWarrior.erase (i);
continue;
}
string sEventString = (*i)->GetName();
string sWeaponStatus = (*i)->ReportWeapons();
if( sWeaponStatus != "")
sEventString += sWeaponStatus;
else
sEventString += " has no weapon";
AddEvent( EVENT_WARRIOR_REPORT, ( * i )-> nCityNo, nColor,sEventString );
i ++;
}
}
void CHeadquarter::WarriorsAttack()
{
list::iterator i = lstWarrior.begin();
for( i; i != lstWarrior.end();i ++) { //循环执行过程中有可能导致 lstWarrior中的某些元素被删,那么 这可能就有问题了 下面
if( (*i)->nStrength <= 0) //5分钟前已经被射杀
continue;
int nCityNo = ( * i )->GetPosition();
//addfor debug
if( nCityNo == 13 )
cout << "";
//gwend
CWarrior * p = pEnemyheadquarter->QueryCityWarrior(nCityNo);
if( p ) {
bool bShouldAttack = false;
if( pKingdom->GetCityFlagColor(nCityNo) == nColor )
bShouldAttack = true;
else if( pKingdom->GetCityFlagColor(nCityNo) == COLOR_NONE) {
if( nColor == COLOR_RED && (nCityNo % 2 == 1))
bShouldAttack = true;
if( nColor == COLOR_BLUE && (nCityNo % 2 == 0))
bShouldAttack = true;
} //有可能反击杀死敌方,然后换旗,结果到这里又主动进攻了
if( bShouldAttack && ( p->GetStrength () > 0 || p->bShotToDeath )) {
int nResult = ( * i )->Attack (p);
if( nResult == 1 ) { //杀死敌人
//由于lsWarrior里面的顺序就是 离敌人近的在前面,所以可以直接这里就奖励了(不行,因为还有反击杀死敌人的情况)
AddToAwardList(*i);
pKingdom->KWarriorWin( * i ) ; //让kingdom处理城市变旗帜的事情
EarnBloodMoney( (*i), nCityNo);
}
else if( nResult < 0 ) { //被敌人反击时杀死
pEnemyheadquarter->AddToAwardList(p);
pKingdom->KWarriorWin(p); //让kingdom处理城市变旗帜的事情
pEnemyheadquarter->EarnBloodMoney(p,nCityNo);
/*
i = lstWarrior.erase (i); //指向被erased的元素的后一个
continue;
erase 统一在report时完成
*/
}
else {
pKingdom->WarDraw(nCityNo);
}
}
else { //如果不是主动进攻,但是敌人已经被箭射杀,那么还算发生了战斗,而且会影响Dragon的fMorale
//还会影响Wolf缴获武器
if( p->bShotToDeath ) { //5分钟前被箭射杀
AddToAwardList(*i);
pKingdom->KWarriorWin( * i ) ; //让kingdom处理城市变旗帜的事情
EarnBloodMoney( (*i), nCityNo);
(*i) -> AddMorale(0.2);
(*i) -> EarnWeapons(p);
}
}
}
}
}
void CHeadquarter::EarnBloodMoney( CWarrior * p, int nCityNo)
{
//获取杀死敌人以后的城市中的生命元
int nMoneyEarned;
nMoneyEarned = pKingdom->QueryCityMoney(nCityNo);
if( nMoneyEarned > 0 ) {
nBloodMoney += nMoneyEarned;
pKingdom->TakeCityMoney(nCityNo);
string sEventString = p->GetName() + " earned " + MyIntToStr(nMoneyEarned) + " elements for his headquarter";
AddEvent( EVENT_EARNMONEY, nCityNo,nColor, sEventString);
}
}
bool MyCompare( const PWARRIOR & p1, const PWARRIOR & p2)
{
if( p1->GetColor() == COLOR_RED)
return p1->nCityNo > p2->nCityNo;
else
return p1->nCityNo < p2->nCityNo;
}
void CHeadquarter::GiveAward()
{
int nSize = vAwardList.size();
sort(vAwardList.begin(), vAwardList.end(),MyCompare);
for( int i = 0;i < vAwardList.size();i ++ ) {
if( nMoney >= 8 ) {
vAwardList[i]->nStrength += 8;
//addfor debug
CWarrior * tmp = vAwardList[i];
int nStrength = tmp->nStrength ;
int nForce = tmp->nForce ;
int nCityNo = tmp->nCityNo;
int nId = tmp->nId ;
//gwend
nMoney -= 8;
}
else
break;
}
vAwardList.clear();
}
void CHeadquarter::AddToAwardList( CWarrior * pWarrior)
{
vAwardList.push_back(pWarrior);
}
void CHeadquarter::AddEvent( EEventType eType, int nCityNo, int nColor, const string & sEventString)
{
pKingdom->AddEvent( eType,nCityNo,nColor,sEventString);
}
void CHeadquarter::PrintMoney() //addfor 2010
{
char szTmp[100];
sprintf(szTmp,"%d",nMoney);
string sEventString = string(szTmp) + " elements in " + GetColorStr() + " headquarter";
if( nColor == COLOR_RED)
pKingdom->AddEvent( EVENT_PRINTMONEY, 0, nColor,sEventString);
else
pKingdom->AddEvent( EVENT_PRINTMONEY, pKingdom->vCity.size() + 1, nColor,sEventString);
}
void CHeadquarter::WarriorBorn()
{
CWarrior * p = NULL;
int nSeqIdx = (nWarriorNo - 1) % 5;
if( nMoney < CWarrior::InitialLifeValue[MakingSeq[nColor][nSeqIdx]])
return ;
nMoney -= CWarrior::InitialLifeValue[MakingSeq[nColor][nSeqIdx]];
int nKindNo = MakingSeq[nColor][nSeqIdx];
switch( nKindNo ) {
case DRAGON:
p = new CDragon(nWarriorNo,CWarrior::InitialLifeValue[nKindNo],CWarrior::InitalForce[nKindNo],nCityNo, this);
break;
case NINJA:
p = new CNinja(nWarriorNo,CWarrior::InitialLifeValue[nKindNo],CWarrior::InitalForce[nKindNo],nCityNo, this);
break;
case ICEMAN:
p = new CIceman(nWarriorNo,CWarrior::InitialLifeValue[nKindNo],CWarrior::InitalForce[nKindNo],nCityNo, this);
break;
case LION:
p = new CLion(nWarriorNo,CWarrior::InitialLifeValue[nKindNo],CWarrior::InitalForce[nKindNo],nCityNo, this);
break;
case WOLF:
p = new CWolf(nWarriorNo,CWarrior::InitialLifeValue[nKindNo],CWarrior::InitalForce[nKindNo],nCityNo, this);
break;
}
lstWarrior.push_back(p);
string sEventString = p->GetName () + " born";
if( nKindNo == LION )
sEventString += "\nIts loyalty is " + MyIntToStr(((CLion*)p)->nLoyalty);
else if( nKindNo == DRAGON) {
char szTmp[40];
//old sprintf(szTmp,"%.2f",((CDragon*)p)->fMorale + EPS);
sprintf(szTmp,"%.2f",((CDragon*)p)->fMorale );
sEventString += "\nIts morale is " +string(szTmp);
}
pKingdom->AddEvent( EVENT_BORN, nCityNo, nColor,sEventString);
nWarriorNo ++;
}
void CKingdom::AddEvent( EEventType eType, int nCityNo,int nColor, const string & sEventString)
{
CEvent tmp(eType, nTimeInMinutes, nCityNo,nColor,sEventString);
vEvent.push_back(tmp);
//addfor debug
//tmp.Output();
//gwend
}
const char * CWeapon::Names[WEAPON_NUM] = {"sword","bomb","arrow" };
const char * CWarrior::Names[WARRIOR_NUM] = { "dragon","ninja","iceman","lion","wolf" };
int CWarrior::InitialLifeValue [WARRIOR_NUM];
int CWarrior::InitalForce [WARRIOR_NUM];
int CWeapon::nArrowForce;
int CLion::nLoyaltyDec;
int CHeadquarter::MakingSeq[2][WARRIOR_NUM] = { { 2,3,4,1,0 },{3,0,1,2,4} };
int main()
{
int nCases;
int M,N,R,K,T;
//freopen("f:\\mydoc\\程序设计实习\\warcraft\\war3\\warcraft.in","r",stdin);
//freopen("f:\\mydoc\\程序设计实习\\warcraft\\war3\\6.in","r",stdin);
cin >> nCases;
int nCaseNo = 1;
while( nCases -- ) {
cin >> M >> N >> R >> K >> T;
CWeapon::nArrowForce = R;
CLion::nLoyaltyDec = K;
//第二行:五个整数,依次是 dragon 、NINJA、iceman、lion、wolf 的初始生命值。它们都大于0小于等于100
int i;
for( i = 0;i < WARRIOR_NUM;i ++ )
cin >> CWarrior::InitialLifeValue[i];
for( i = 0;i < WARRIOR_NUM;i ++ )
cin >> CWarrior::InitalForce[i];
CKingdom MyKingdom(N,M);
MyKingdom.Run(T);
cout << "Case " << nCaseNo++ << ":" << endl;
MyKingdom.OutputResult();
}
return 0;
}
2022.1 魔兽世界之三的题目:
045:魔兽世界三(开战)
描述
魔兽世界的西面是红魔军的司令部,东面是蓝魔军的司令部。两个司令部之间是依次排列的若干城市,城市从西向东依次编号为1,2,3 .... N ( N <= 20)。红魔军的司令部算作编号为0的城市,蓝魔军的司令部算作编号为N+1的城市。司令部有生命元,用于制造武士。
两军的司令部都会制造武士。武士一共有dragon 、ninja、iceman、lion、wolf 五种。每种武士都有编号、生命值、攻击力这三种属性。
双方的武士编号都是从1开始计算。红方制造出来的第n 个武士,编号就是n。同样,蓝方制造出来的第n 个武士,编号也是n。
武士在刚降生的时候有一个初始的生命值,生命值在战斗中会发生变化,如果生命值减少到0(生命值变为负数时应当做变为0处理),则武士死亡(消失)。
武士可以拥有武器。武器有三种,sword, bomb,和arrow,编号分别为0,1,2。
sword的攻击力是使用者当前攻击力的20%(去尾取整)。
bomb的攻击力是使用者当前攻击力的40%(去尾取整),但是也会导致使用者受到攻击,对使用者的攻击力是对敌人取整后的攻击力的1/2(去尾取整)。Bomb一旦使用就没了。
arrow的攻击力是使用者当前攻击力的30%(去尾取整)。一个arrow用两次就没了。
武士降生后就朝对方司令部走,在经过的城市如果遇到敌人(同一时刻每个城市最多只可能有1个蓝武士和一个红武士),就会发生战斗。战斗的规则是:
在奇数编号城市,红武士先发起攻击
在偶数编号城市,蓝武士先发起攻击
战斗开始前,双方先对自己的武器排好使用顺序,然后再一件一件地按顺序使用。编号小的武器,排在前面。若有多支arrow,用过的排在前面。排好序后,攻击者按此排序依次对敌人一件一件地使用武器。如果一种武器有多件,那就都要用上。每使用一件武器,被攻击者生命值要减去武器攻击力。如果任何一方生命值减为0或小于0即为死去。有一方死去,则战斗结束。
双方轮流使用武器,甲用过一件,就轮到乙用。某一方把自己所有的武器都用过一轮后,就从头开始再用一轮。如果某一方没有武器了,那就挨打直到死去或敌人武器用完。武器排序只在战斗前进行,战斗中不会重新排序。
如果双方武器都用完且都还活着,则战斗以平局结束。如果双方都死了,也算平局。
有可能由于武士自身攻击力太低,而导致武器攻击力为0。攻击力为0的武器也要使用。如果战斗中双方的生命值和武器的状态都不再发生变化,则战斗结束,算平局。
战斗的胜方获得对方手里的武器。武士手里武器总数不超过10件。缴获武器时,按照武器种类编号从小到大缴获。如果有多件arrow,优先缴获没用过的。
如果战斗开始前双方都没有武器,则战斗视为平局。如果先攻击方没有武器,则由后攻击方攻击。
不同的武士有不同的特点。
编号为n的dragon降生时即获得编号为n%3 的武器。dragon在战斗结束后,如果还没有战死,就会欢呼。
编号为n的ninjia降生时即获得编号为n%3 和(n+1)%3的武器。ninja 使用bomb不会让自己受伤。
编号为n的iceman降生时即获得编号为n%3 的武器。iceman每前进一步,生命值减少10%(减少的量要去尾取整)。
编号为n的lion降生时即获得编号为n%3 的武器。lion 有“忠诚度”这个属性,其初始值等于它降生之后其司令部剩余生命元的数目。每前进一步忠诚度就降低K。忠诚度降至0或0以下,则该lion逃离战场,永远消失。但是已经到达敌人司令部的lion不会逃跑。lion在己方司令部可能逃跑。
wolf降生时没有武器,但是在战斗开始前会抢到敌人编号最小的那种武器。如果敌人有多件这样的武器,则全部抢来。Wolf手里武器也不能超过10件。如果敌人arrow太多没法都抢来,那就先抢没用过的。如果敌人也是wolf,则不抢武器。
以下是不同时间会发生的不同事件:
在每个整点,即每个小时的第0分, 双方的司令部中各有一个武士降生。
红方司令部按照iceman、lion、wolf、ninja、dragon 的顺序制造武士。
蓝方司令部按照lion、dragon、ninja、iceman、wolf 的顺序制造武士。
制造武士需要生命元。
制造一个初始生命值为m 的武士,司令部中的生命元就要减少m 个。
如果司令部中的生命元不足以制造某本该造的武士,那就从此停止制造武士。
在每个小时的第5分,该逃跑的lion就在这一时刻逃跑了。
在每个小时的第10分:所有的武士朝敌人司令部方向前进一步。即从己方司令部走到相邻城市,或从一个城市走到下一个城市。或从和敌军司令部相邻的城市到达敌军司令部。
在每个小时的第35分:在有wolf及其敌人的城市,wolf要抢夺对方的武器。
在每个小时的第40分:在有两个武士的城市,会发生战斗。
在每个小时的第50分,司令部报告它拥有的生命元数量。
在每个小时的第55分,每个武士报告其拥有的武器情况。
武士到达对方司令部后就算完成任务了,从此就呆在那里无所事事。
任何一方的司令部里若是出现了敌人,则认为该司令部已被敌人占领。
任何一方的司令部被敌人占领,则战争结束。战争结束之后就不会发生任何事情了。
给定一个时间,要求你将从0点0分开始到此时间为止的所有事件按顺序输出。事件及其对应的输出样例如下:
1) 武士降生
输出样例:000:00 blue dragon 1 born
表示在0点0分,编号为1的蓝魔dragon武士降生
如果造出的是lion,那么还要多输出一行,例:
000:00 blue lion 1 born
Its loyalty is 24
表示该lion降生时的忠诚度是24
2) lion逃跑
输出样例:000:05 blue lion 1 ran away
表示在0点5分,编号为1的蓝魔lion武士逃走
3) 武士前进到某一城市
输出样例:
000:10 red iceman 1 marched to city 1 with 20 elements and force 30
表示在0点10分,红魔1号武士iceman前进到1号城市,此时他生命值为20,攻击力为30
对于iceman,输出的生命值应该是变化后的数值
4) wolf抢敌人的武器
000:35 blue wolf 2 took 3 bomb from red dragon 2 in city 4
表示在0点35分,4号城市中,红魔1号武士wolf 抢走蓝魔2号武士dragon 3个bomb。为简单起见,武器不写复数形式
5) 报告战斗情况
战斗只有3种可能的输出结果:
000:40 red iceman 1 killed blue lion 12 in city 2 remaining 20 elements
表示在0点40分,1号城市中,红魔1号武士iceman 杀死蓝魔12号武士lion后,剩下生命值20
000:40 both red iceman 1 and blue lion 12 died in city 2
注意,把红武士写前面
000:40 both red iceman 1 and blue lion 12 were alive in city 2
注意,把红武士写前面
6) 武士欢呼
输出样例:003:40 blue dragon 2 yelled in city 4
7) 武士抵达敌军司令部
输出样例:001:10 red iceman 1 reached blue headquarter with 20 elements and force 30
(此时他生命值为20,攻击力为30)对于iceman,输出的生命值和攻击力应该是变化后的数值
8) 司令部被占领
输出样例:003:10 blue headquarter was taken
9)司令部报告生命元数量
000:50 100 elements in red headquarter
000:50 120 elements in blue headquarter
表示在0点50分,红方司令部有100个生命元,蓝方有120个
10)武士报告情况
000:55 blue wolf 2 has 2 sword 3 bomb 0 arrow and 7 elements
为简单起见,武器都不写复数形式。elements一律写复数,哪怕只有1个
交代武器情况时,次序依次是:sword,bomb, arrow。
输出事件时:
首先按时间顺序输出;
同一时间发生的事件,按发生地点从西向东依次输出. 武士前进的事件, 算是发生在目的地。
在一次战斗中有可能发生上面的 5 至 6 号事件。这些事件都算同时发生,其时间就是战斗开始时间。一次战斗中的这些事件,序号小的应该先输出。
两个武士同时抵达同一城市,则先输出红武士的前进事件,后输出蓝武士的。
对于同一城市,同一时间发生的事情,先输出红方的,后输出蓝方的。
显然,8号事件发生之前的一瞬间一定发生了7号事件。输出时,这两件事算同一时间发生,但是应先输出7号事件
虽然任何一方的司令部被占领之后,就不会有任何事情发生了。但和司令部被占领同时发生的事件,全都要输出。
输入
第一行是t,代表测试数据组数
每组样例共三行。
第一行,4个整数 M,N,K, T。其含义为:
每个司令部一开始都有M个生命元( 1 <= M <= 100000)
两个司令部之间一共有N个城市( 1 <= N <= 20 )
lion每前进一步,忠诚度就降低K。(0<=K<=100)
要求输出从0时0分开始,到时间T为止(包括T) 的所有事件。T以分钟为单位,0 <= T <= 6000
第二行:五个整数,依次是 dragon 、ninja、iceman、lion、wolf 的初始生命值。它们都大于0小于等于200
第三行:五个整数,依次是 dragon 、ninja、iceman、lion、wolf 的攻击力。它们都大于0小于等于200
输出
对每组数据,先输出一行:
Case n:
如对第一组数据就输出 Case 1:
然后按恰当的顺序和格式输出到时间T为止发生的所有事件。每个事件都以事件发生的时间开头,时间格式是“时: 分”,“时”有三位,“分”有两位。
样例输入
1
20 1 10 400
20 20 30 10 20
5 5 5 5 5
样例输出
Case 1:
000:00 blue lion 1 born
Its loyalty is 10
000:10 blue lion 1 marched to city 1 with 10 elements and force 5
000:50 20 elements in red headquarter
000:50 10 elements in blue headquarter
000:55 blue lion 1 has 0 sword 1 bomb 0 arrow and 10 elements
001:05 blue lion 1 ran away
001:50 20 elements in red headquarter
001:50 10 elements in blue headquarter
002:50 20 elements in red headquarter
002:50 10 elements in blue headquarter
003:50 20 elements in red headquarter
003:50 10 elements in blue headquarter
004:50 20 elements in red headquarter
004:50 10 elements in blue headquarter
005:50 20 elements in red headquarter
005:50 10 elements in blue headquarter
提示
请注意浮点数精度误差问题。OJ上的编译器编译出来的可执行程序,在这方面和你电脑上执行的程序很可能会不一致。5 * 0.3 的结果,有的机器上可能是 15.00000001,去尾取整得到15,有的机器上可能是14.9999999,去尾取整后就变成14。因此,本题不要写 5 * 0.3,要写 5 * 3 / 10。
#include
#include
#include
#include
#include
using namespace std;
int soldier_HP[5];
char soldier_name[5][20] = {"iceman", "lion", "wolf", "ninja", "dragon"};
char weapon_name[3][20] = {"sword", "bomb", "arrow"};
int soldier_force[5];
int city_number, time_limited;
//different soldier class
//model class
class csoldier
{
public:
int HP, force, locate, id;
int weapon[4];
int weapen_amount;
csoldier() { memset(weapon, 0, sizeof(weapon)); }
virtual ~csoldier(){}
//第n次交手应该使用的武器,n已经考虑过经过循环处理
int getweapon(int &n)
{
bool flag = false;
if (weapen_amount <= n) flag = true;
if (n <= weapon[0])
{
++n;
if(flag) n = 1;
return 0;
}
else if (n <= weapon[0] + weapon[1])
{
weapon[1]--;
weapen_amount--;
if(flag) n = 1;
return 1;
}
else if (n <= weapon[3] + weapon[0] + weapon[1])
{
weapon[3]--;
weapen_amount--;
if(flag) n = 1;
return 2;
}
else if (n <= weapen_amount)
{
weapon[2]--;
weapon[3]++;
++n;
if(flag) n = 1;
return 2;
}
cout << "wrong!" << endl;
}
virtual void out_name() = 0;
friend class battlefield;
};
class dragon:public csoldier
{
private:
friend class battlefield;
//constructor
dragon(int n, int color):csoldier()
{
weapon[n % 3] = 1;
weapen_amount = 1;
force = soldier_force[4];
locate = ((color == 0)? 0 : city_number + 1);
HP = soldier_HP[4];
id = n;
}
//destructor
~dragon(){}
virtual void out_name()
{
cout << "dragon " << id;
}
};
class ninja:public csoldier
{
private:
friend class battlefield;
ninja(int n, int color) :csoldier()
{
weapon[n % 3] = 1;
weapon[(n + 1) % 3] = 1;
weapen_amount = 2;
force = soldier_force[3];
locate = ((color == 0) ? 0 : city_number + 1);
HP = soldier_HP[3];
id = n;
}
~ninja(){}
virtual void out_name()
{
cout << "ninja " << id;
}
};
class iceman:public csoldier
{
private:
friend class battlefield;
iceman(int n, int color) :csoldier()
{
weapon[(n % 3)] = 1;
weapen_amount = 1;
force = soldier_force[0];
locate = ((color == 0) ? 0 : city_number + 1);
HP = soldier_HP[0];
id = n;
}
virtual void out_name()
{
cout << "iceman " << id;
}
};
class lion:public csoldier
{
private:
friend class battlefield;
int loyalty;
lion(int n, int color, int hp) :csoldier(), loyalty(hp)
{
weapon[n % 3] = 1;
weapen_amount = 1;
force = soldier_force[1];
locate = ((color == 0) ? 0 : city_number + 1);
HP = soldier_HP[1];
id = n;
cout << "Its loyalty is " << loyalty << endl;
}
virtual void out_name()
{
cout << "lion " << id;
}
public:
static int K;
};
int lion::K = 0;
class wolf:public csoldier
{
wolf(int n, int color) :csoldier()
{
weapen_amount = 0;
force = soldier_force[2];
locate = ((color == 0) ? 0 : city_number + 1);
HP = soldier_HP[2];
id = n;
}
virtual void out_name()
{
cout << "wolf " << id;
}
private:
friend class battlefield;
};
class battlefield
{
private:
int hour, minute, soldier_total[2], cur[2];
int HP[2];
char name[2][20];
bool produce_end[2];//if production is carrying on, it is false, if else it is true
csoldier ***head;
int soldier[5];//in the order of iceman¡¢lion¡¢wolf¡¢ninja¡¢dragon
public:
int arr[2][5] = { {0, 1, 2, 3, 4} ,{1, 4, 3, 0, 2} };
//int arr[5] = {1, 4, 3, 0, 2};
battlefield(int n) :HP{ n, n}, hour(0), minute(0), produce_end{ true,true }
{
soldier_total[0] = soldier_total[1] = 0;
cur[0] = cur[1] = -1;
strcpy(name[0], "red");
strcpy(name[1], "blue");
memset(soldier, 0, sizeof(soldier));
head = new csoldier** [city_number + 2];
for (int i = 0; i < city_number + 2; ++i)
{
head[i] = new csoldier*[4];
//memset(head[i], NULL, sizeof(csoldier*) * 4);
memset(head[i], 0, sizeof(csoldier*) * 4);
}
}
//输出当前时间
void out_time()
{
cout << setfill('0') << setw(3) << hour << ':' << setfill('0') << setw(2) << minute;
return;
}
//base produce soldiers. if base produce soldier sucessfully, return true;if else return false;
bool produce(int color)
{
if(produce_end[color] == false)
return false;
cur[color] = (cur[color] + 1) % 5;
int t = arr[color][cur[color]];
if(HP[color] >= soldier_HP[t])
{
HP[color] -= soldier_HP[t];
soldier[t]++;
soldier_total[color]++;
out_time();
cout << ' ' << name[color] << ' ' << soldier_name[t] << ' ' << soldier_total[color] << " born"<< endl;
int pos = ((color == 0) ? 0 : city_number + 1);
switch(t)
{
case 0: head[pos][color] = new iceman(soldier_total[color], color);break;
case 1: head[pos][color] = new lion(soldier_total[color], color, HP[color]);break;
case 2: head[pos][color] = new wolf(soldier_total[color], color);break;
case 3: head[pos][color] = new ninja(soldier_total[color], color);break;
case 4: head[pos][color] = new dragon(soldier_total[color], color);break;
}
return true;
}
else
{
produce_end[color] = false;
return false;
}
}
//renew location
void clear()
{
for (int i = 0; i <= city_number + 1; ++i)
{
head[i][0] = head[i][2];
head[i][1] = head[i][3];
head[i][2] = head[i][3] = NULL;
}
return;
}
//soldiers start moving
bool march()
{
bool flag = true;
if (head[1][1] != NULL)
{
if (typeid(*head[1][1]) == typeid(iceman))
head[1][1]->HP -= head[1][1]->HP / 10;
out_time();
cout << " blue "; head[1][1]->out_name();
printf(" reached red headquarter with %d elements and force %d\n", head[1][1]->HP, head[1][1]->force);
head[0][3] = head[1][1];
out_time();
cout << " red headquarter was taken" << endl;
flag = false;
}
for (int i = 1; i <= city_number; ++i)
{
if (head[i - 1][0] != NULL)
{
if (typeid(*head[i - 1][0]) == typeid(iceman))
head[i - 1][0]->HP -= head[i - 1][0]->HP / 10;
out_time();
cout << " red "; head[i - 1][0]->out_name();
printf(" marched to city %d with %d elements and force %d\n",i, head[i-1][0]->HP, head[i-1][0]->force);
head[i][2] = head[i - 1][0];
}
if (head[i + 1][1] != NULL)
{
if (typeid(*head[i + 1][1]) == typeid(iceman))
head[i + 1][1]->HP -= head[i + 1][1]->HP / 10;
out_time();
cout << " blue "; head[i + 1][1]->out_name();
printf(" marched to city %d with %d elements and force %d\n", i, head[i + 1][1]->HP, head[i + 1][1]->force);
head[i][3] = head[i + 1][1];
}
}
if (head[city_number][0] != NULL)
{
if (typeid(*head[city_number][0]) == typeid(iceman))
head[city_number][0]->HP -= head[city_number][0]->HP / 10;
out_time();
cout << " red "; head[city_number][0]->out_name();
printf(" reached blue headquarter with %d elements and force %d\n", head[city_number][0]->HP, head[city_number][0]->force);
head[city_number + 1][2] = head[city_number][0];
out_time();
cout << " blue headquarter was taken" << endl;
flag = false;
}
clear();
return flag;
}
//judge whether lion run away
void run_away()
{
for (int i = 0; i <= city_number + 1; ++i)
{
for (int t = 0; t < 2; ++t)
{
if (head[i][t] != NULL && typeid(*head[i][t]) == typeid(lion))
{
auto p = (lion *)head[i][t];
if (p->loyalty <= 0)
{
out_time();
cout << ' ' << name[t];
cout << " lion " << head[i][t]->id << " ran away" << endl;
delete head[i][t];
head[i][t] = NULL;
continue;
}
p->loyalty -= lion::K;
}
}
}
return;
}
//winner snatch loser's weapon
void snatch_weapon(csoldier *p, csoldier *q)
{
for (int i = 0; i < 4; ++i)
{
while (q->weapon[i] > 0 && p->weapen_amount < 10)
{
p->weapon[i]++;
q->weapon[i]--;
p->weapen_amount++;
}
}
return;
}
void out_weapen(int t)
{
switch(t)
{
case 0: cout << weapon_name[0];break;
case 1: cout << weapon_name[1];break;
case 2: cout << weapon_name[2];break;
case 3: cout << weapon_name[2];break;
}
return;
}
//wolf snatch enemy's weapon
void w_snatch_weapon(csoldier *p, csoldier *q)
{
//bool flag = true;
int t = 0, s = 0;
while (q->weapon[t] == 0)++t;
if (10 - p->weapen_amount <= q->weapon[t])
{
p->weapon[t] += 10 - p->weapen_amount;
s += 10 - p->weapen_amount;
p->weapen_amount = 10;
q->weapen_amount -= s;
q->weapon[t] -= s;
return;
}
else
{
p->weapon[t] += q->weapon[t];
s += q->weapon[t];
p->weapen_amount += q->weapon[t];
q->weapon[t] -= s;
q->weapen_amount -= s;
if (t == 2 && q->weapon[3] > 0)
{
t = 3;
if (10 - p->weapen_amount <= q->weapon[t])
{
p->weapon[t] += 10 - p->weapen_amount;
s += 10 - p->weapen_amount;
p->weapon[t] -= 10 - p->weapen_amount;
p->weapen_amount -= 10 - p->weapen_amount;
p->weapen_amount = 10;
}
else
{
p->weapon[t] += q->weapon[t];
s += q->weapon[t];
q->weapen_amount -= q->weapon[t];
p->weapen_amount += q->weapon[t];
q->weapon[t] = 0;
}
}
cout << s << ' ';
out_weapen(t);
return;
}
}
//wolf snatch enemy's weapon
void snatch()
{
for (int i = 1; i <= city_number; ++i)
{
csoldier *p[2] = { head[i][0], head[i][1] };
if (p[0] != NULL && p[1] != NULL)
{
if (typeid(*p[0]) != typeid(wolf) && typeid(*p[1]) != typeid(wolf))
continue;
else if (typeid(*p[0]) != typeid(wolf))
{
if(p[0]->weapen_amount == 0 || p[1]->weapen_amount == 10)
continue;
out_time(); cout << " blue ";p[1]->out_name();
cout << " took ";
w_snatch_weapon(p[1], p[0]);
cout << " from red ";
p[0]->out_name();cout << " in city " << i << endl;
}
else if (typeid(*p[1]) != typeid(wolf))
{
if(p[1]->weapen_amount == 0 || p[0]->weapen_amount == 10)
continue;
out_time(); cout << " red ";p[0]->out_name();
cout << " took ";
w_snatch_weapon(p[0], p[1]);
cout << " from blue ";
p[1]->out_name();cout << " in city " << i << endl;
}
else
continue;
}
}
}
//fight
void fight()
{
for (int i = 1; i <= city_number; ++i)
{
if (head[i][0] == NULL || head[i][1] == NULL)
continue;
int r = i % 2, L = r ^ 1, n[2] = {1, 1}, w, flag = 5, check[4] = {0}, cnt = 0;
while (true)
{
//判断是否局势改变,若不改变则为平局
r = r ^ 1;
L = L ^ 1;
if (cnt == 0)
{
if (check[0] == head[i][0]->HP && check[1] == head[i][1]->HP && check[2] == head[i][0]->weapen_amount && check[3] == head[i][1]->weapen_amount)
{
flag = 0;//all alive
break;
}
check[0] = head[i][0]->HP;
check[1] = head[i][1]->HP;
check[2] = head[i][0]->weapen_amount;
check[3] = head[i][1]->weapen_amount;
cnt = 10;
}
cnt--;
if (head[i][L]->weapen_amount == 0 && head[i][r]->weapen_amount == 0)
{
flag = 0;//alive
break;
}
if(head[i][r]->weapen_amount == 0)
continue;
w = head[i][r]->getweapon(n[r]);
// if(head[i][1]->id == 10)
// cout << r << ' ' << "use weapen " << w << " in city " << i <HP -= head[i][r]->force / 5; break;
case 1:
h = head[i][r]->force * 2 / 5;
head[i][L]->HP -= h;
if(typeid(*head[i][r]) != typeid(ninja))
head[i][r]->HP -= h / 2;
break;
case 2:
head[i][L]->HP -= head[i][r]->force * 3 / 10; break;
default:
break;
}
if (head[i][L]->HP <= 0 && head[i][r]->HP <= 0)
{
flag = 3;//all died
break;
}
else if (head[i][L]->HP <= 0)
{
if (L == 0)
{
flag = 2; //blue win
break;
}
else
{
flag = 1; //red win
break;
}
}
else if (head[i][r]->HP <= 0)
{
if (r == 0)
{
flag = 2; //blue win
break;
}
else
{
flag = 1; //red win
break;
}
}
}
out_time();
switch (flag)
{
case 0:
cout << " both red ";
head[i][0]->out_name();
cout << " and blue ";
head[i][1]->out_name();
cout << " were alive in city " << i << endl;
break;
case 3:
cout << " both red ";
head[i][0]->out_name();
cout << " and blue ";
head[i][1]->out_name();
cout << " died in city " << i << endl;
delete head[i][0];
delete head[i][1];
head[i][0] = NULL;
head[i][1] = NULL;
break;
case 1:
cout << " red ";
head[i][0]->out_name();
cout << " killed blue ";
head[i][1]->out_name();
printf(" in city %d remaining %d elements\n", i, head[i][0]->HP);
snatch_weapon(head[i][0], head[i][1]);
delete head[i][1];
head[i][1] = NULL;
break;
case 2:
cout << " blue ";
head[i][1]->out_name();
cout << " killed red ";
head[i][0]->out_name();
printf(" in city %d remaining %d elements\n", i, head[i][1]->HP);
snatch_weapon(head[i][1], head[i][0]);
delete head[i][0];
head[i][0] = NULL;
break;
default:
break;
}
for (int t = 0; t < 2; ++t)
{
if (head[i][t] != NULL && typeid(*head[i][t]) == typeid(dragon))
{
out_time(); cout << ' ' << name[t] << ' ';
head[i][t]->out_name();
cout << " yelled in city " << i << endl;
}
}
}
}
//base report condition
void base_report()
{
out_time();
printf(" %d elements in red headquarter\n", HP[0]);
out_time();
printf(" %d elements in blue headquarter\n", HP[1]);
return;
}
//soldier report
void soldier_report()
{
for (int i = 0; i < city_number + 1; ++i)
{
for(int t = 0; t < 2; ++t)
if (head[i][t] != NULL)
{
out_time();
cout << ' ' << name[t] << ' ';
head[i][t]->out_name();
cout << " has " << head[i][t]->weapon[0] << " sword " << head[i][t]->weapon[1] << " bomb "
<< head[i][t]->weapon[2] + head[i][t]->weapon[3] << " arrow and " << head[i][t]->HP << " elements" << endl;
}
}
return;
}
//check whether time is legal
bool check_time()
{
if (hour * 60 + minute > time_limited)
return false;
else
return true;
}
bool run()
{
minute = 0;
if (!check_time()) return false;
produce(0);
produce(1);
minute = 5;
if (!check_time()) return false;
run_away();
minute = 10;
if (!check_time()) return false;
if(!march())
return false;
minute = 35;
if (!check_time()) return false;
snatch();
minute = 40;
if (!check_time()) return false;
fight();
minute = 50;
if (!check_time()) return false;
base_report();
minute = 55;
if (!check_time()) return false;
soldier_report();
hour++;
return true;
}
};
int main()
{
int n, hp, cnt = 0;
cin >> n;
while(n--)
{
cout << "Case " << ++cnt <<':'<< endl;
cin >> hp >> city_number >> lion::K >> time_limited;
battlefield Battle(hp);
cin >> soldier_HP[4] >> soldier_HP[3] >> soldier_HP[0] >> soldier_HP[1] >> soldier_HP[2];
cin >> soldier_force[4] >> soldier_force[3] >> soldier_force[0] >> soldier_force[1] >> soldier_force[2];
while (Battle.run());
}
return 0;
}