796子矩阵的和
二维前缀和
#include<iostream>
using namespace std;
const int maxx = 1e3+10;
int ma[maxx][maxx];
int main(){
int n,m,q;
cin>>n>>m>>q;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>ma[i][j];
ma[i][j]=ma[i-1][j]+ma[i][j-1]-ma[i-1][j-1]+ma[i][j];
}
}
while(q--){
int x1,x2,y1,y2;
cin>>x1>>y1>>x2>>y2;
cout<<ma[x2][y2]-ma[x1-1][y2]-ma[x2][y1-1]+ma[x1-1][y1-1]<<endl;
}
return 0;
}
1096地牢大师
bfs模板
#include<iostream>
#include<queue>
using namespace std;
string m[110][110];
int dir[6][3] = {{0,0,1},{0,1,0},{1,0,0},{0,0,-1},{0,-1,0},{-1,0,0}};
int L,R,C;
int sl,sr,sc;
struct Node{
int l;
int r;
int c;
int step;
};
int bfs(){
Node cur={sl,sr,sc,0};
queue<Node> q;
q.push(cur);
while(q.size()){
Node pre = q.front();
q.pop();
for(int i=0;i<6;i++){
int nexl = pre.l+dir[i][0];
int nexr = pre.r+dir[i][1];
int nexc = pre.c+dir[i][2];
int nexStep = pre.step+1;
if(nexl==L||nexl<0||nexr==R||nexr<0||nexc==C||nexc<0){
continue;
}
if(m[nexl][nexr][nexc]=='#'){
continue;
}
if(m[nexl][nexr][nexc]=='.'){
Node nex = {nexl,nexr,nexc,nexStep};
q.push(nex);
m[nexl][nexr][nexc] = '#';
}
if(m[nexl][nexr][nexc]=='E'){
return nexStep;
}
}
}
return -1;
}
int main(){
while(true){
cin>>L>>R>>C;
if(L==0){
break;
}
getchar();
for(int i=0;i<L;i++){
for(int j=0;j<R;j++){
getline(cin,m[i][j]);
}
string tmp;
getline(cin,tmp);
}
for(int i=0;i<L;i++){
for(int j=0;j<R;j++){
for(int k=0;k<C;k++){
if(m[i][j][k]=='S'){
sl=i;
sr=j;
sc=k;
}
}
}
}
int res = bfs();
if(res == -1){
cout<<"Trapped!"<<endl;
}else{
printf("Escaped in %d minute(s).\n",res);
}
}
return 0;
}
1224交换瓶子
很巧妙的思路,在遍历时不是让a[j]
复原,而是让a[a[j]]
复原
1
e
4
1e4
1e4的时间复杂度也够用
#include<iostream>
using namespace std;
const int maxx = 1e4+10;
int a[maxx];
int main(){
int N;
cin>>N;
for(int i=1;i<=N;i++){
cin>>a[i];
}
bool res = false;
int ans = 0;
for(int i=1;i<=N;i++){
for(int j=1;j<=N;j++){
if(a[j]!=j){
swap(a[j],a[a[j]]);
ans++;
}
}
}
cout<<ans<<endl;
return 0;
}
1240完全二叉树的权值
使用数组模拟完全二叉树,注意完全二叉树的性质,即
首先根节点的下标为
1
,层数从
1
开始
首先根节点的下标为1,层数从1开始
首先根节点的下标为1,层数从1开始
对于第
i
层,结点下标为
[
2
i
−
1
,
2
i
−
1
]
对于第i层,结点下标为[2^{i-1},2^i-1]
对于第i层,结点下标为[2i−1,2i−1]
#include<cmath>
#include<iostream>
using namespace std;
const int maxx = 1e5+10;
typedef long long ll;
int main(){
int N;
cin>>N;
int a[maxx];
for(int i=1;i<=N;i++){
cin>>a[i];
}
int maxd = (int)(log(N)/log(2))+1;
ll maxsum = -1e10-10;
//2^(n-1)~2^n-1
int ans = 1;
for(int i=1;i<=maxd;i++){
ll sum = 0;
for(int j=(int)pow(2,i-1);j<=(int)pow(2,i)-1 && j<=N;j++){
sum+=a[j];
}
if(maxsum<sum){
maxsum=sum;
ans = i;
}
}
cout<<ans<<endl;
return 0;
}
895最长上升子序列
模板中的模板
#include<iostream>
using namespace std;
const int maxx = 1e3+100;
int a[maxx];
int dp[maxx];
int main(){
int N;
cin>>N;
for(int i=0;i<N;i++){
cin>>a[i];
}
int ans = 0;
for(int i=0;i<N;i++){
for(int j=0;j<i;j++){
if(a[i]>a[j]){
dp[i]=max(dp[i],dp[j]+1);
ans = max(ans,dp[i]);
}
}
}
cout<<ans+1<<endl;
return 0;
}
1015摘花生
dp模板
#include<iostream>
using namespace std;
const int maxx = 110;
int m[maxx][maxx];
int main(){
int T;
cin>>T;
while(T--){
int R,C;
cin>>R>>C;
for(int r=1;r<=R;r++){
for(int c=1;c<=C;c++){
cin>>m[r][c];
}
}
for(int r=1;r<=R;r++){
for(int c=1;c<=C;c++){
m[r][c] += max(m[r-1][c],m[r][c-1]);
}
}
cout<<m[R][C]<<endl;
}
return 0;
}
1211蚂蚁感冒
首先可以把他那个倒转方向的操作,看做相互穿过
假如蚂蚁0往右走,那他右边的往左走的蚂蚁肯定会感冒,接着他左边的向右走的也会感冒
但是如果他右边没有往左走的,那他左边往右走的不会感冒
所以要特判一下
蚂蚁0往左走同理
#include<iostream>
using namespace std;
const int maxx = 60;
int a[maxx];
int main(){
int N;
cin>>N;
cin>>a[0];
//左右两边朝着第一只蚂蚁走的个数
int left=0,right=0;
for(int i=1;i<N;i++){
cin>>a[i];
//朝着第一只蚂蚁走的都可能会被干扰
if(a[i]>0&&(abs(a[i])<abs(a[0]))){
left++;
}else if(a[i]<0&&(abs(a[i])>abs(a[0]))){
right++;
}
}
int ans = left+right+1;
//左边没有朝着蚂蚁0且蚂蚁0往左走
if(left==0 && a[0]<0){
ans=1;
}
//右边没有朝着蚂蚁0且蚂蚁0往右走
if(right==0 && a[0]>0){
ans=1;
}
cout<<ans<<endl;
return 0;
}
1216 饮料换购
#include<iostream>
using namespace std;
int main(){
int a,b;
int ans = 0;
cin>>a;
b=0;
while(true){
ans += a;
b += a;
a = b/3;
b = b%3;
if(a==0)break;
}
cout<<ans<<endl;
return 0;
}
4867整除数
#include<iostream>
using namespace std;
typedef long long ll;
int main(){
int n,k;
cin>>n>>k;
int m = n%k;
if(m==0){
cout<<n+k<<endl;
}else{
cout<<n+k-m<<endl;
}
return 0;
}
4867整除数
#include<iostream>
using namespace std;
typedef long long ll;
int main(){
int n,k;
cin>>n>>k;
int m = n%k;
if(m==0){
cout<<n+k<<endl;
}else{
cout<<n+k-m<<endl;
}
return 0;
}
104货仓选址
取中位数,即左边和右边的货舱数量一致
#include<iostream>
#include<algorithm>
using namespace std;
const int maxx = 1e5+10;
int a[maxx];
int main(){
int N;
cin>>N;
for(int i=1;i<=N;i++){
cin>>a[i];
}
sort(a+1,a+N+1);
int addr;
if(N%2){
addr = a[N/2+1];
}else{
addr = (a[N/2]+a[N/2+1])>>1;
}
int ans = 0;
for(int i=1;i<=N;i++){
ans += abs(a[i]-addr);
}
cout<<ans<<endl;
return 0;
}
1219移动距离
为了方便取余运算,减少心智压力,将所有的数都减一,即
1 2 3 4 5 6变为0 1 2 3 4 5
#include<iostream>
#include<algorithm>
using namespace std;
void get(int m,int w,int& r,int& c){
int tmpr = m/w;
int tmpc = m%w;
if(tmpr%2){
tmpc = w-tmpc-1;
}
r = tmpr;
c = tmpc;
}
int main(){
int w,m,n;
cin>>w>>m>>n;
m--;
n--;
//计算m的行和列
int mr,mc,nr,nc;
get(m,w,mr,mc);
get(n,w,nr,nc);
int ans = abs(mr-nr)+abs(mc-nc);
cout<<ans<<endl;
return 0;
}
1055股票买卖
#include<iostream>
using namespace std;
const int maxx = 1e5+10;
int dp[maxx][2];
int a[maxx];
int main(){
int N;
cin>>N;
//不让dp[1][0]使用后者作为最大值
dp[0][1]=-100000;
for(int i=1;i<=N;i++){
cin>>a[i];
dp[i][0]=max(dp[i-1][0],dp[i-1][1]+a[i]);
dp[i][1]=max(dp[i-1][1],dp[i-1][0]-a[i]);
}
cout<<dp[N][0]<<endl;
return 0;
}
1245特别数的和
简单枚举
#include<iostream>
using namespace std;
bool check(int i){
bool res = false;
while(i){
int mod = i%10;
if(mod==2||mod==9||mod==0||mod==1){
res=true;
break;
}
i/=10;
}
return res;
}
int main(){
int n;
cin>>n;
int sum=0;
for(int i=1;i<=n;i++){
if(check(i)){
sum+=i;
}
}
cout<<sum<<endl;
return 0;
}