总结
动态变化
转换状态(减少变量)
string反转:reverse(t.begin(),t.end());
2739. 总行驶距离
错误解法
cpp
class Solution {
public:
int distanceTraveled(int mainTank, int additionalTank) {
int ans=0;
while(mainTank){
int s=mainTank/5;
ans+=mainTank*10;
mainTank=0;
if(additionalTank){
if(s<=additionalTank){
additionalTank-=s;
mainTank+=s;
}
else {
mainTank+=additionalTank;
additionalTank=0;
}
}
}
return ans;
}
};
我把 mainTank 一次性全烧完了,再按 mainTank / 5 一次性补油
但题目的补油规则是:
每消耗 5 升主油箱油 ,且副油箱还有油时,立刻 转 1 升到主油箱。
也就是说:补进来的油可以立刻参与"消耗5升"的运算
所以推荐模拟做法
cpp
class Solution {
public:
int distanceTraveled(int mainTank, int additionalTank) {
int ans=0;
while(mainTank>=5){
mainTank-=5;
ans+=50;
if(additionalTank){
additionalTank--;
mainTank++;
}
}
return ans+mainTank*10;
}
};
3546. 等和矩阵分割 I

S和T-S相等,转化为2*S=T
现在只要找S
注意开long long
cpp
class Solution {
public:
bool canPartitionGrid(vector<vector<int>>& grid) {
long long total=0;
for(int i=0;i<grid.size();i++){
for(int j=0;j<grid[i].size();j++){
total+=grid[i][j];
}
}
long long sumA=0;
for(int i=0;i<grid.size();i++){
for(int j=0;j<grid[i].size();j++){
sumA+=grid[i][j];
}
if(sumA*2==total)return true;
}
long long sumB=0;
for(int i=0;i<grid[0].size();i++){
for(int j=0;j<grid.size();j++){
sumB+=grid[j][i];
}
if(sumB*2==total)return true;
}
return false;
}
};
401. 二进制手表
cpp
class Solution {
public:
vector<string> readBinaryWatch(int turnedOn) {
vector<string> ans;
char s[6];
for (uint8_t h = 0; h < 12; h++) {
for (uint8_t m = 0; m < 60; m++) {
if (popcount(h) + popcount(m) == turnedOn) {
sprintf(s, "%d:%02d", h, m);
ans.push_back(s);
}
}
}
return ans;
}
};
注释版
cpp
class Solution {
public:
vector<string> readBinaryWatch(int turnedOn) {
vector<string> ans;
//结尾是'\0'
char s[6];
// uint8_t:无符号 8 位整数类型
//用unsigned int也行(popcount函数接收无符号整型)
for (unsigned int h = 0; h < 12; h++) {
for (unsigned int m = 0; m < 60; m++) {
// popcount(x):x 的二进制中有多少个 1
//头文件:#include <bit>
if (popcount(h) + popcount(m) == turnedOn) {
// sprintf 是 C 语言的字符串格式化函数
sprintf(s, "%d:%02d", h, m);
ans.push_back(s);
}
}
}
return ans;
}
};
P1007 独木桥
重要思想:假设士兵碰面时交换灵魂
cpp
#include<iostream>
using namespace std;
int main(){
int L,n;
cin>>L>>n;
if(n==0){
cout<<0<<" "<<0;
return 0;
}
int t;
int maxAns=-1;
int minAns=-1;
for(int i=0;i<n;i++){
cin>>t;
minAns=max(minAns,min(t-0,L+1-t));
maxAns=max(maxAns,max(t-0,L+1-t));
}
cout<<minAns<<" "<<maxAns;
return 0;
}
P1015 [NOIP 1999 普及组] 回文数
1、string反转:reverse(t.begin(),t.end());
2、模拟加法:carry和digit
3、toNum和toChar转化
cpp
#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
using namespace std;
int n;
string m;
int toNum(char c){
if(c>='0'&&c<='9')return c-'0';
else return c-'A'+10;
}
char toChar(int x){
if(x>=0&&x<=9)return x+'0';
else return x-10+'A';
}
bool jud(string m){
int left=0;
int right=m.size()-1;
while(left<=right){
if(m[left++]!=m[right--])return false;
}
return true;
}
string add(string a,string b){
string ans="";
int carry=0;
for(int i=a.size()-1;i>=0;i--){
int sum=toNum(a[i])+toNum(b[i])+carry;
int digit=sum%n;
carry=sum/n;
ans+=toChar(digit);
}
if(carry)ans+=toChar(carry);
reverse(ans.begin(),ans.end());
return ans;
}
int main(){
cin>>n>>m;
for(int i=0;i<=30;i++){
if(jud(m)){
cout<<"STEP="<<i;
return 0;
}
string t=m;
reverse(t.begin(),t.end());
m=add(t,m);
}
cout<<"Impossible!";
return 0;
}
P1031 [NOIP 2002 提高组] 均分纸牌
贪心,往后传和往前传的公式是一样的
- 如果 ai>num,则 ai+1=ai+1+ai−num,ai=num;
- 如果 ai<num,则 ai+1=ai+1−num+ai,ai=num;
- 如果 ai=num,则不需要进行任何操作。
cpp
#include<iostream>
#include<vector>
using namespace std;
int main(){
int n;
cin>>n;
vector<int>s(n);
int num=0;
for(int i=0;i<n;i++){
cin>>s[i];
num+=s[i];
}
num/=n;
int ans=0;
for(int i=0;i<n-1;i++){
if(s[i]!=num){
s[i+1]+=s[i]-num;
ans++;
}
}
cout<<ans;
return 0;
}
