电子版教材链接
:
我通过百度网盘分享的文件:深入浅出程序设计…pdf
链接:https://pan.baidu.com/s/1kmF8wZLnK3Zci7s1ffjRzw
提取码:Ra3Q
复制这段内容打开「百度网盘APP即可获取」
// 法一: 简洁实现
#include
#include
using namespace std;
char str[100010];
int cnt=0;
void show(int n){
int a=0,b=0;
for(int i=0;i<cnt;i++){
if(str[i]=='W') a++;
if(str[i]=='L') b++;
if((a>=n||b>=n)&&abs(a-b)>=2){
cout<<a<<":"<<b<<endl;
a=b=0;
}
}
//新的一轮刚开始,或上一局没有打完
cout<<a<<":"<<b<<endl;
}
int main(){
char ch;
while(cin>>ch&&ch!='E'){
if(ch=='W'||ch=='L'){
str[cnt++]=ch;
}
}
show(11);
cout<<endl;
show(21);
return 0;
}
// 法二:完整实现
#include
using namespace std;
char n;
int l,m;
int a[62503];
int main()
{
for(int i = 0;cin >> n && n != 'E';i++)
{
if(n == 'W') a[i] = 1;
if(n == 'L') a[i] = 2;
}
// 11分制
for(int i = 0;1;i++)
{
if(a[i] == 1) l++;
if(a[i] == 2) m++;
if(a[i] == 0)
{
cout << l << ":" << m << endl << endl;
break;
}
if(l - m >= 2 || m - l >= 2)
{
if(l >= 11 || m >= 11)
{
cout << l << ":" << m << endl;
l = 0;
m = 0;
}
}
}
l = 0;
m = 0;
// 21分制
for(int i = 0;1;i++)
{
if(a[i] == 1) l++;
if(a[i] == 2) m++;
if(a[i] == 0)
{
cout << l << ":" << m << endl; //把未打完的残局也输出出去
break;
}
if(l - m >= 2 || m - l >= 2)
{
if(l >= 21 || m >= 21)
{
cout << l << ":" << m << endl;
l = 0;
m = 0;
}
}
}
return 0;
}
// 法一:开桶
#include
using namespace std;
int n,m;
char arr[105][105];
const int dx[] = {1,1,1,0,0,-1,-1,-1};
const int dy[] = {-1,0,1,-1,1,-1,0,1};
// 这边定义了该点周围八个方向的点的偏移量
int main()
{
cin >> n >> m;
for(int i = 1;i<=n;i++)
{
for(int j = 1;j<=m;j++)
{
cin >> arr[i][j];
}
}
for(int i = 1;i<=n;i++)
{
for(int j = 1;j<=m;j++)
{
if(arr[i][j] != '*')
{
int cnt = 0;
for(int k = 0;k<8;k++)
{
if(arr[i+dx[k]][j+dy[k]] == '*') cnt++;
}
cout << cnt;
}
else cout << '*';
}
cout << endl;
}
return 0;
}
// 法二:dfs
#include
using namespace std;
int n,m;
char arr[105][105];
void dfs(int x,int y){//需要返回空类型,定义void函数
if(arr[x][y]=='0'){
for(int dx=-1;dx<=1;dx++){
for(int dy=-1;dy<=1;dy++){
int nx=dx+x,ny=dy+y;
if(0<=nx&&nx<n&&0<=ny&&ny<m&&arr[nx][ny]=='*')//八连通循环 ,且必须不越界
arr[x][y]+=1;//如果是雷的话将那一个点加1
}
}
}
return;//将那个点加完之后就返回继续找下一个点
}
int main()
{
string s;
cin >> n >> m;
for(int i = 0; i < n; i++)
{
cin >> s;
for(int j = 0; j < m; j++)
{
arr[i][j] = s[j];
if(arr[i][j] == '?')
{
arr[i][j] = '0';
}
}
}
for(int i = 0;i<n;i++)
{
for(int j = 0;j<m;j++)
dfs(i,j);
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++)
cout<<arr[i][j];//按序输出每一个点
cout << endl;
}
return 0;
}
#include
using namespace std;
struct nihao{
bool dict;
string name;
}arr[100005];
int main()
{
bool s;
int len,cnt = 0; // cnt表示的是最后我们要找的人的索引
cin >> n >> m;
for(int i = 0;i<n;i++)
{
cin >> arr[i].dict >> arr[i].name;
}
for(int i = 0;i<m;i++)
{
cin >> s >> len; // 0表示左数,1表示右数 ;其中朝内向左等价于朝外向右,即00和11是一致的,我们主要考虑朝内向右为正 01
if(arr[cnt].dict == 0 && s== 0 || arr[cnt].dict == 1 && s == 1)
{
cnt -= len;
}
else
cnt += len;
if(cnt >=n)
cnt-=n;
else if(cnt<0)
cnt+=n;
}
cout << arr[cnt].name << endl;
return 0;
}
直接使用取模的方式从低位往高位进行进位,这里是高精度加上高精度
#include
using namespace std;
#define maxn 520
int a[maxn],b[maxn],c[maxn];
int main()
{
string A,B;
cin >> A >> B;
int len = max(A.length(),b.length());
for(int i = A.length()-1,j = 1;i>=0;i--,j++)
a[j] = A[i] - '0';
for(int i = B.length()-1,j = 1;i>=0;i--,j++)
b[j] = B[i] - '0';
for(int i = 1;i<=len;i++)
{
c[i] += a[i] + b[i];
c[i+1] = c[i] / 10;
c[i] %= 10;
}
if(c[len+1]) // 最后进位可能会导致位数增加
len++;
for(int i = len;i>=1;i--)
cout << c[i];
return 0;
}
拓展
高精度减法注意: 这里的A一定要大于B!
Q:为什么要考虑前导0
A:
1000 - 1 = 0999 会输出0999而不是999
#include
using namespace std;
#define maxn 520
int a[maxn], b[maxn], c[maxn];
int main()
{
string A, B;
cin >> A >> B;
int lenA = A.length();
int lenB = B.length();
int len = max(lenA, lenB);
// 倒序存入数组 a[], b[]
for (int i = lenA - 1, j = 1; i >= 0; i--, j++)
a[j] = A[i] - '0';
for (int i = lenB - 1, j = 1; i >= 0; i--, j++)
b[j] = B[i] - '0';
// 高精度减法:c = a - b(要求 a ≥ b)
for (int i = 1; i <= len; i++) {
c[i] = a[i] - b[i];
if (c[i] < 0) {
c[i] += 10;
a[i + 1]--; // 向高位借 1
}
}
// 去除前导零
while (len > 1 && c[len] == 0) len--; // 1000-1 = 0999,要把前导0减去
// 输出结果
for (int i = len; i >= 1; i--)
cout << c[i];
cout << endl;
return 0;
}
这里是高精度乘高精度的板子题
先计算贡献,最后一次性处理进位,一次性取模进位的复杂度比多次取模进位的复杂度要低得多
Q:为什么要考虑前导0的情况
A:
100 × 100 = 10000
最大位数 = 3 + 3 = 6
实际结果 = 5 位 → c[6] = 0,导致我们输出的不是10000而是010000
#include
using namespace std;
#define maxn 5010
int a[maxn],b[maxn],c[maxn];
int main()
{
string A,B;
cin >> A >> B;
int lena = A.length(),lenb = B.length();
for(int i = lena-1;i>=0;i--) a[lena-i] = A[i] - '0';
for(int i = lenb-1;i>=0;i--) b[lenb-i] = B[i] - '0';
for(int i = 1;i<=lena;i++)
for(int j = 1;j<=lenb;j++)
c[i+j-1] += a[i] * b[j]; //计算贡献 a[i]*b[j]的进位贡献都在[i+j-1]上
int len = lena + lenb; // 乘积的位数不超过两数的位数之和
for(int i = 1;i<=len;i++){
c[i+1] += c[i] / 10; // 处理进位
c[i] %=10;
}
while (len > 1 && c[len] == 0) len--; // 去除前导零
for(int i = len;i>=1;i--)
cout << c[i];
return 0;
}
拓展
高精度乘单精度#include
using namespace std;
#define maxn 5010
int a[maxn], c[maxn]; // a 是大整数,c 是结果
int b; // 单精度整数
int main()
{
string A;
cin >> A >> b; // 读入大整数和单精度整数
int lena = A.length();
for(int i = lena - 1; i >= 0; i--)
a[lena - i] = A[i] - '0'; // 逆序存储,大端 -> 小端
int len = lena;
for(int i = 1; i <= lena; i++) {
c[i] += a[i] * b; // 乘以单精度数
}
// 处理进位
for(int i = 1; i <= len + 10; i++) {
c[i + 1] += c[i] / 10;
c[i] %= 10;
}
while(len > 1 && c[len] == 0) len++; // 预估最大长度后再定位真实长度
while(len > 1 && c[len] == 0) len--; // 去除前导 0
for(int i = len; i >= 1; i--)
cout << c[i];
cout << endl;
return 0;
}
拓展
高精度除法tips: 高精度除法是从高位往低位处理,所以不需要倒置,这里实现的是高精度大数除以小数的版本,更严谨的高精度版本会在后续的vector容器部分进行展示。
设被除数为字符串 A
,除数为整数 b
,求商 C = A / b
,余数 r = A % b
。处理方法如下:
从高位到低位 依次处理 A
的每一位字符。
设置当前的“部分被除数”为 r * 10 + A[i]
。
当前位的商为 (r * 10 + A[i]) / b
,更新余数 r = (r * 10 + A[i]) % b
。
依次填入商的每一位,最后去除前导零即可。
这种做法等价于手动进行“竖式除法”中从左向右的计算
#include
using namespace std;
#define maxn 5010
int a[maxn], c[maxn]; // a 存储被除数,c 存储结果商
int main() {
string A;
int b; // 除数是一个普通整数
cin >> A >> b;
int lena = A.length();
// 以高位在前方式读入数组(a[1] 是最高位)
for(int i = 0; i < lena; i++) {
a[i+1] = A[i] - '0';
}
int r = 0; // 当前余数
for(int i = 1; i <= lena; i++) {
int current = r * 10 + a[i]; // 当前部分被除数
c[i] = current / b; // 当前位的商
r = current % b; // 更新余数
}
// 去除前导零
int s = 1;
while(s < lena && c[s] == 0) s++;
for(int i = s; i <= lena; i++)
cout << c[i];
if (s > lena) cout << 0; // 特判商为0的情况
cout << r << endl; // 输出余数
return 0;
}
#include
using namespace std;
#define maxn 100
struct Bigint{
int len,a[maxn]; // 使用len记录位数(长度),a为记录每个数位的数组
Bigint(int x = 0) // 通过初始化是的这个大整数能够表示整型x,默认为0
{
memset(a,0,sizeof(a));
for(len = 1;x;len++)
a[len] = x%10 , x/=10;
len--;
}
int &operator[](int i){
return a[i]; //重载[],可以直接使用x[i]表示x.a[i],这一步可以省去
}
void flatten(int L) // 因为把不是一位数的数都处理为一位数,所以函数名叫做展平
{
// 一口气处理1到L范围内的进位并且重置长度,但需要保证L不小于有效长度
len = L;
for(int i = 1;i<=len;i++)
a[i+1] += a[i]/10,a[i] %=10 ;
while (len > 1 && a[len] == 0) len--; // 去除前导零
}
void print(){ // 输出
for(int i= len;i>=1;i--)
printf("%d",a[i]);
}
};
// 重载加法和乘法运算符
Bigint operator+(Bigint a,Bigint b){ // 表示两个Bigint类相加,返回一个Bigint类
Bigint c;
int len = max(a.len,b.len);
for(int i = 1;i<=len;i++)
c[i] += a[i]+b[i]; // 计算贡献
c.flatten(len+1); // 答案不超过len+1位,使用len+1做一遍展平处理进位(多的位数会被当前导0被处理掉)
return c;
}
// 这里由于阶乘每次乘的数都是不超过1e9的int类型,所以我们只需要使用高精度*int类型的乘法就够了
Bigint operator*(Bigint a,int b){ // 表示Bigint乘整型变量,返回一个Bigint类
Bigint c;
int len = a.len;
for(int i = 1 ;i<=len;i++)
c[i] = a[i] * b; // 计算贡献
c.flatten(len+11); // int类型最长10位,这样做可以一遍展平处理进位(多的位数会被当前导0被处理掉)
return c;
}
int main()
{
Bigint ans(0),fac(1) ; // 调用构造函数进行初始化
int n;
cin >> n;
for(int i = 1;i<=n;i++){
fac = fac*i;
ans = ans+fac;
}
ans.print(); // 输出答案
}
#include
#include
using namespace std;
int square[505][505],temp[505][505];
// 先简单的使用r = 1为一半数据的情况进行模拟分析,找出规律后使用规律构建函数进行解决
void spin(int x,int y,int r)//顺时针旋转90°
{
for(int i=x-r;i<=x+r;i++)
{
for(int k=y-r;k<=y+r;k++)
temp[i][k]=square[i][k]; // 新开辟一个数组存储原来的信息,否则后续的更新中可能会存在覆盖
// 比如你第一个旋转是 a[x-1][y-1] = a[x+1][y-1] 但是第三个旋转是 a[x-1][y+1] = a[x-1][y-1] 如果不使用新数组这两行代码就相当于 a[x-1][y+1] = a[x+1][y-1] 但是根据分析,这个是不成立的,所以每次更新我们需要使用一个新数组记录原数组的信息,所以上面的旋转过程应该是 a[x-1][y-1] = temp[x+1][y-1],a[x-1][y+1] = temp[x-1][y-1];
}
int x1=x+r,y1=y-r;
for(int i=x-r;i<=x+r;i++)
{
for(int k=y-r;k<=y+r;k++)
{
square[i][k]=temp[x1][y1];
x1--;
}
x1=x+r,y1++;
}
}
void spin_(int x,int y,int r)//逆时针旋转90°
{
for(int i=x-r;i<=x+r;i++)
{
for(int k=y-r;k<=y+r;k++)
temp[i][k]=square[i][k];
}
int x1=x-r,y1=y+r;
for(int i=x-r;i<=x+r;i++)
{
for(int k=y-r;k<=y+r;k++)
{
square[i][k]=temp[x1][y1];
x1++;
}
y1--,x1=x-r;
}
}
int main()
{
int n,m,t=0;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int k=1;k<=n;k++)
square[i][k]=++t;
}//首先给矩阵赋值
int x,y,r,z;
for(int i=0;i<m;i++)
{
cin>>x>>y>>r>>z;
if(z==0)
spin(x,y,r);
else if(z==1)
spin_(x,y,r);
}
for(int i=1;i<=n;i++)
{
for(int k=1;k<=n;k++)
cout<<square[i][k]<<" ";
cout<<endl;
}
}
#include
using namespace std;
int N,N_A,N_B;
int arr[205],brr[205],a[205],b[205],ans = 0,bns = 0;
void nihao(int a[],int b[],int & ans,int &bns)
{
for(int i = 0;i<N;i++)
{
if(a[i] == 0 && b[i] == 0 || a[i] == 1 && b[i] == 1 || a[i] == 2 && b[i] == 2 || a[i] == 3 && b[i] == 3 || a[i] == 4 && b[i] == 4) ans +=0,bns+=0;
if(a[i] == 0 && b[i] == 1) bns++;
if(a[i] == 0 && b[i] == 2) ans++;
if(a[i] == 0 && b[i] == 3) ans++;
if(a[i] == 0 && b[i] == 4) bns++;
if(a[i] == 1 && b[i] == 0) ans++;
if(a[i] == 1 && b[i] == 2) bns++;
if(a[i] == 1 && b[i] == 3) ans++;
if(a[i] == 1 && b[i] == 4) bns++;
if(a[i] == 2 && b[i] == 0) bns++;
if(a[i] == 2 && b[i] == 1) ans++;
if(a[i] == 2 && b[i] == 3) bns++;
if(a[i] == 2 && b[i] == 4) ans++;
if(a[i] == 3 && b[i] == 0) bns++;
if(a[i] == 3 && b[i] == 1) bns++;
if(a[i] == 3 && b[i] == 2) ans++;
if(a[i] == 3 && b[i] == 4) ans++;
if(a[i] == 4 && b[i] == 0) ans++;
if(a[i] == 4 && b[i] == 1) ans++;
if(a[i] == 4 && b[i] == 2) bns++;
if(a[i] == 4 && b[i] == 3) bns++;
}
}
int main()
{
cin >> N >> N_A >> N_B;
for(int i = 0;i<N_A;i++)
{
cin >> arr[i];
}
for(int i = 0;i<N_B;i++)
{
cin >> brr[i];
}
for (int i = 0; i < N; i++) {
a[i] = arr[i % N_A];
}
for (int i = 0; i < N; i++) {
b[i] = brr[i % N_B];
}
nihao(a,b,ans,bns);
cout << ans << " " << bns;
return 0;
}
// 法一: dfs暴力搜索
#include
using namespace std;
const int dx[4]={-1,0,1,0};//上、右、下、左四个方向
const int dy[4]={0,1,0,-1};
int cx,cy,ct;//记录奶牛
int fx,fy,ft;//记录john
bool f[21][21],v[21][21][4][21][21][4];//f表示地图是否能走,v表示这种情况是否有出现过:农夫在 (fx, fy) 且朝向 ft,奶牛在 (cx, cy) 且朝向 ct。
void dfs(int k)
{
if(cx==fx && cy==fy)//如果抓到了牛
{
printf("%d\n",k);//输出
exit(0);
}
if(v[fx][fy][ft][cx][cy][ct]==false)//如果这种情况出现过
{
printf("0\n");
exit(0);
}
v[fx][fy][ft][cx][cy][ct]=false;//把这种情况设置为出现过
//找奶牛的方向
if(f[cx+dx[ct]][cy+dy[ct]]==false)//如果这个方向不能走
{
ct++;if(ct==4) ct=0;//改变方向
}
else cx=cx+dx[ct],cy=cy+dy[ct];//如果可以走就走
//找john的方向
if(f[fx+dx[ft]][fy+dy[ft]]==false)
{
ft++;if(ft==4) ft=0;
}
else fx=fx+dx[ft],fy=fy+dy[ft];
dfs(k+1);//往下搜索
}
int main()
{
int i,j;char st[21];
memset(f,false,sizeof(f));//为了方便判断边界,一开始就当做不能走吧
for(i=1;i<=10;i++)
{
scanf("%s",st+1);//输入
for(j=1;j<=10;j++)
{
if(st[j]=='.') f[i][j]=true;//如果能走
if(st[j]=='F') fx=i,fy=j,f[i][j]=true;//如果是john
if(st[j]=='C') cx=i,cy=j,f[i][j]=true;//如果是牛
}
}
ct=ft=0;//一开始是向北
memset(v,true,sizeof(v));//各种情况都是可以的
dfs(0);//开始搜索
return 0;
}
// 法二: 模拟骗分
#include
using namespace std ;
//基本初始:
char mp[11][11] ; //创建地图
int xa , ya , xb , yb ; //创建变量表示农夫和牛的位置( a 为农夫, b 为牛, x 为行, y为列)
int lxa , lya , lxb , lyb ; //创建变量表示农夫和牛移动后的位置(移动可能不成立)
int fa = 1 , fb = 1 ; //创建变量表示农夫和牛的方向( 1 为北、 2 为东、 3 为南、 4 为西)
int ans = 0 ; //创建变量表示时间(输出结果)
//农夫移动函数:
void yda(){
//平移区:
if ( fa == 1 ){ //当方向为北时
lxa = xa - 1 ; //行向上移动(减 1 )
lya = ya ; //列不动
}
if ( fa == 2 ){ //当方向为东时
lxa = xa ; //行不动
lya = ya + 1 ; //列向右移动(加 1 )
}
if ( fa == 3 ){ //当方向为南时
lxa = xa + 1 ; //行向下移动(加 1 )
lya = ya ; //列不动
}
if ( fa == 4 ){ //当方向为西时
lxa = xa ; //行不动
lya = ya - 1 ; //列向左移动(减 1 )
}
//判定区:
if ( lxa >= 1 && lya >= 1 && lya <= 10 && lxa <= 10 && mp[lxa][lya] == '.' ){ //当移动后位置在地图内且为空地
xa = lxa ; //行位置
ya = lya ; //列位置
}
else{ //不成立
fa++ ; //方向转变
if ( fa > 4 ){ //当方向值大于西侧
fa = 1 ; //变回北侧
}
}
}
//牛移动函数:
void ydb(){
//平移区
if ( fb == 1 ){ //当方向为北时
lxb = xb - 1 ; //行向上移动(减 1 )
lyb = yb ; //列不动
}
if ( fb == 2 ){ //当方向为东时
lxb = xb ; //行不动
lyb = yb + 1 ; //列向右移动(加 1 )
}
if ( fb == 3 ){ //当方向为南时
lxb = xb + 1 ; //行向下移动(加 1 )
lyb = yb ; //列不动
}
if ( fb == 4 ){ //当方向为西时
lxb = xb ; //行不动
lyb = yb - 1 ; //列向左移动(减 1 )
}
//判定区:
if ( lxb >= 1 && lyb >= 1 && lyb <= 10 && lxb <= 10 && mp[lxb][lyb] == '.' ){ //当移动后位置在地图内且为空地
xb = lxb ; //行位置
yb = lyb ; //列位置
}
else{ //不成立
fb++ ; //方向转变
if ( fb > 4 ){ //当方向值大于西侧
fb = 1 ; //变回北侧
}
}
}
//主函数:
int main(){
//输入区:
for ( int i = 1 ; i <= 10 ; i++ ){ //基本二维输入行
for ( int j = 1 ; j <= 10 ; j++ ){ //基本二维输入列
cin >> mp[i][j] ; //输入
if ( mp[i][j] == 'F' ){ //当输入为农夫位置时,将其存储至农夫的位置
xa = i ; //储存行
ya = j ; //储存列
mp[i][j] = '.' ; //为判断方便,将其变为空地
}
if ( mp[i][j] == 'C' ){ //当输入为牛位置时,将其存储至牛的位置
xb = i ; //储存行
yb = j ; //储存列
mp[i][j] = '.' ; //为判断方便,将其变为空地
}
}
}
//模拟区:
while(1){
yda() ; //农夫移动
ydb() ; //牛移动
ans++ ; //时间增加
if ( ans > 10000 ){ //此处为骗分,如果大于 10000 还是没有重合,即无法重合
cout << 0 ; //直接输出 0
return 0 ; //结束程序
}
if ( xa == xb && ya == yb ){ //如果重合(行列均相同)
cout << ans ; //输出时间
return 0 ; //结束程序
}
}
}
#include
using namespace std;
int n, tmp;
bool first = true; // 引入一个 flag 标志变量来记录是否已经输出过一项,为True表示还在处理首项
int main() {
scanf("%d", &n);
for (int i = n; i >= 0; i--) {
scanf("%d", &tmp);
if (tmp == 0) continue;
if (!first) {
if (tmp > 0) printf("+");
else printf("-");
} else {
if (tmp < 0) printf("-");
first = false;
}
int absTmp = abs(tmp);
if (i == 0) {
printf("%d", absTmp);
} else if (i == 1) {
if (absTmp == 1) printf("x");
else printf("%dx", absTmp);
} else {
if (absTmp == 1) printf("x^%d", i);
else printf("%dx^%d", absTmp, i);
}
}
// 如果所有项都是0
if (first) printf("0");
return 0;
}
#include
using namespace std;
int p1,p2,p3,i=0,k;
char ch[300],be,af,f,j,p;//p用于输出;
int main() {
scanf("%d%d%d%s",&p1,&p2,&p3,ch);//输入;
while(ch[i]){//当ch[i]有值时;
be=ch[i-1];af=ch[i+1];f=ch[i];//f存储ch[i],便于判断;
if(f=='-'&&af>be&&(be>='0'&&af<='9'||be>='a'&&af<='z')){//意思是ch[i]若为'-',就判断其前后是否满足条件,满足就进入循环
if (p3 == 1) { // 升序展开
for (j = be + 1; j < af; j++) {
p = j;
if (p1 == 2 && p >= 'a' && p <= 'z') p = p - 32;
else if (p1 == 3) p = '*';
for (k = 0; k < p2; k++) printf("%c", p);
}
} else { // 降序展开
for (j = af - 1; j > be; j--) {
p = j;
if (p1 == 2 && p >= 'a' && p <= 'z') p = p - 32;
else if (p1 == 3) p = '*';
for (k = 0; k < p2; k++) printf("%c", p);
}
}
}
else
printf("%c",f);//如果ch[i]是非'-'或者其前后不满足条件,就原样输出;
i++;//一定要放在后面,不然会出错;
}
return 0;
}
这道模拟题需要把题意先理解清楚后才能做,基本没用到什么算法,就是一个模拟题
#include
using namespace std;
struct node{
int num,tim;
}e[22][22];
int n,m;//n工件数 m机器数及工序数
int mac[22][40000];
int ord[400];
int now[22];
int be[22];
int main()
{
scanf("%d %d",&m,&n);
int tmp=n*m;
for(int i=1;i<=tmp;i++) scanf("%d",&ord[i]);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&e[i][j].num);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&e[i][j].tim);
int ans=0;
for(int i=1;i<=tmp;i++)//大模拟
{
int whi=ord[i];//第几个工件
int wha=(++now[whi]);//第几步骤
int ma=e[whi][wha].num;//哪个机器
int go=e[whi][wha].tim;//多少时间
int cnt=0,end;
for(int j=be[whi]+1;;j++)
{
if(mac[ma][j]==0) cnt++;
else cnt=0;
if(cnt==go)
{
end=j;
break;
}
}
for(int j=end-go+1;j<=end;j++) mac[ma][j]=1;
be[whi]=end;
ans=max(ans,end);
}
printf("%d",ans);
return 0;
}
使用了结构体排序和自定义cmp排序,我把第九章放在第八章前也是为了这道题可以更容易理解一些
#include
using namespace std;
int n;
struct nihao{
string na,zw,xzw; // 名字,过去的位置,现在更新后的位置
long long bg; // 帮贡
int le,h; // 等级和序号
}ab[115];
int change(string a){
if (a=="BangZhu") return 0;
if (a=="FuBangZhu") return 1;
if (a=="HuFa") return 2;
if (a=="ZhangLao") return 3;
if (a=="TangZhu") return 4;
if (a=="JingYing") return 5;
if (a=="BangZhong") return 6;
}
int cmp1(nihao x,nihao y){
if (x.bg==y.bg) return x.h<y.h; // 帮贡相等按序号排序
else return x.bg>y.bg; // 否则按帮贡来排
}
int cmp2(nihao x,nihao y){
if (change(x.xzw)==change(y.xzw)){
if (x.le==y.le) return x.h<y.h; //现职位相等且等级相等,按输入顺序排列
return x.le>y.le; //等级不等按等级排序
}
return change(x.xzw)<change(y.xzw); //现职位不等按现职位大小排序,使用自定义change函数,把职位赋值化,数字越小者越强
}
int main(){
cin>>n;
for (int i=1;i<=n;i++){
cin>>ab[i].na>>ab[i].zw>>ab[i].bg>>ab[i].le;
ab[i].h=i;
}
sort(ab+4,ab+1+n,cmp1);
for (int i=1;i<=n;i++){
if (i==1) ab[i].xzw="BangZhu";
else if (i==2||i==3) ab[i].xzw="FuBangZhu";
else if (i==4||i==5) ab[i].xzw="HuFa";
else if (i>=6&&i<=9) ab[i].xzw="ZhangLao";
else if (i>=10&&i<=16) ab[i].xzw="TangZhu";
else if (i>=17&&i<=41) ab[i].xzw="JingYing";
else ab[i].xzw="BangZhong";
}
sort(ab+1,ab+1+n,cmp2);
for (int i=1;i<=n;i++){
cout<<ab[i].na<<" "<<ab[i].xzw<<" "<<ab[i].le<<endl;
}
return 0;
}
本题使用高精度乘单精度的板子加上数位统计即可
#include
using namespace std;
int a[5000]; // 用于高精度,最多支持到几千位阶乘
int main() {
int T;
cin >> T;
while (T--) {
int n, d, len = 1;
cin >> n >> d;
a[0] = 1;
// 计算 n!
for (int i = 2; i <= n; i++) {
int carry = 0;
for (int j = 0; j < len; j++) {
int temp = a[j] * i + carry;
a[j] = temp % 10;
carry = temp / 10;
}
while (carry) {
a[len++] = carry % 10;
carry /= 10;
}
}
// 统计数字 d 出现次数
int cnt = 0;
for (int i = 0; i < len; i++)
if (a[i] == d) cnt++;
cout << cnt << endl;
}
return 0;
}
习题8-9 最大乘积 P149
习题8-10 麦森数 P1045