https://codeforces.com/contest/1106/problem/A
每次选取一个‘x’ 判断四角是不是’x’
#include <iostream>
#include <fstream>
using namespace std;
char matr[505][505];
bool check(int x,int y)
{
for(int i=-1; i<2; i++)
for(int j=-1; j<2; j++)
if(abs(i)==1&&abs(j)==1)
if(matr[i+x][j+y]!='X')
return false;
return true;
}
int main()
{
int n;
while(cin>>n)
{
for(int i=0; i<n; i++)
cin>>matr[i];
int ans=0;
for(int i=0; i<n; i++)
for(int j=0 ; j<n ; j++)
if(matr[i][j] == 'X' )
if( check(i,j) )
ans++;
cout<<ans<<endl;
}
}
https://codeforces.com/contest/1106/problem/B
排序
#include <bits/stdc++.h>
using namespace std;
const long long maxn=1e5;
struct node
{
long long x,y,z;
} arr[maxn],tag[maxn];
bool cmp(node a,node b)
{
return a.y<b.y;
}
int main()
{
long long n,m;
while(cin>>n>>m)
{
for(long long i=0; i<n; i++)
{
cin>>arr[i].x;
}
for(long long i=0; i<n; i++)
{
cin>>arr[i].y;
tag[i].y=arr[i].y;
tag[i].z=i;
}
sort(tag,tag+n,cmp);
long long mx=0,x,y,s;
for(long long i=0; i<m; i++)
{
cin>>y>>x;
y--;
long long ans=0;
if(arr[y].x < x)
{
// cout<<"asd "<<endl;
ans+=arr[y].x*arr[y].y;
x-=arr[y].x;
arr[y].x=0;
long long mex;
if(mx<n)
{
mex=tag[mx].z;
while( x>arr[mex].x&&mx<n)
{
ans+=arr[mex].x*arr[mex].y;
x-=arr[mex].x;
arr[mex].x=0;
mx++;
mex=tag[mx].z;
}
if(mx<n)
{
ans+=x*arr[mex].y;
arr[mex].x-=x;
cout<<ans<<endl;
}
else
{
mx=n+10;
cout<<0<<endl;
}
}
else
cout<<"0"<<endl;
}
else
{
arr[y].x-=x;
cout<<arr[y].y*x<<endl;
}
// for(long long j=0;j<n;j++)
//cout<<arr[j].x<<' ';cout<<endl;
}
}
}
https://codeforces.com/contest/1106/problem/C
排序- - 大小 不想写
平方和最小 肯定是让每组数的大小尽可能平均 - -。
排序 两两组合就是最优 = = 可以证明。
https://codeforces.com/contest/1106/problem/D
题意 :一个图,每次可以走可以到达的任何一个点,求遍历的最小字典序。
解法:使用set,每次添加可以到达的点,选一个最小的弹出。
set真好用
set的主要功能就是相当于一个插入后能自动排序的数组(从小到大)。但是要注意一个数值在set中只能出现1次或0次
用法:
一.如何定义:
1.注意头文件:#include ;
2.定义set类型的数组:set<类型> 名称;例如—— set s;
-
(1). insert() ;//插入元素; 例如——s.insert(a);(插入元素a)
(2) erase() ;//删除排序后的第几个元素;例如——s.erase(a);(删除第a个元素)
例如——s.erase(a,b);(删除第a个到第b个元素)
(3). begin() ;//返回set的第一个元素; 例如——a=*s.begin();
(4). end() ;//返回set的最后一个元素; 例如——a=*s.end();
(5). clear() ;//清空set内的元素; 例如——a=s.clear();
(6). empty() ;//判断set内元素是否为空; 例如——a=s.empty();
(7). max_size() ;//返回set能包含的元素的最大个数; 例如——a=s.max_size();
(8). size() ;//返回当前元素个数; 例如——a=s.size();
作者:涅槃重塑
来源:CSDN
原文:https://blog.csdn.net/qq_41181881/article/details/81268138
版权声明:本文为博主原创文章,转载请附上博文链接!
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5;
vector<int > tag[maxn];
set<int > nodes;
int pes[maxn];
int main()
{
int n,m;
while(cin>>n>>m)
{
for(int i=0;i<=n;i++)
{
pes[i]=0;
tag[i].clear();
}
int x,y;
for(int i=0;i<m;i++)
{
cin>>x>>y;
tag[x].push_back(y);
tag[y].push_back(x);
}
int q=1;
nodes.insert(1);
pes[1]=1;
while(nodes.size() )
{
int son=*nodes.begin();
nodes.erase(nodes.begin());
cout<<son<<' ';
q++;
for(int i=0;i<tag[son].size(); i++)
{
int se=tag[son][i];
if(!pes[se])
{
pes[se]=1;
nodes.insert(se);
}
}
}
cout<<endl;
}
}
https://codeforces.com/contest/1106/problem/E
题意:
在长度为n的时间轴上,有k个红包,每个红包有领取时间段[s,t],价值w,以及领了个这个红包之后,在时间d到来之前无法再进行领取操作。每次领取的策略是取当前可领取红包中w最大的,w相同时取d最大的。再给m个干扰机会,一个干扰机会可以使其在任意一个x这个时间点无法进行领取操作直到x+1。问最优使用不超过m次干扰下,将领取的最小红包价值总和。(n,k<=1e5,m<=200)
dp(i,j) i位置被打扰了j次能获得的最少硬币
预处理:寻找每个时刻所要选取的红包。 使用multiset 作为容器 每个时刻添加红包,然后结尾时刻删除红包。
之后对每个时刻dp 此时刻是否阻止选择红包。每次选择最小值。
跑记忆化搜索dfs.
最后的结果就是最小值。
#include <bits/stdc++.h>
using namespace std;
const long long maxn=1e5+5;
//in 为可选红包,out为不可选红包
vector< pair <int,long long > > in[maxn],out[maxn];
//代表每个时刻的最佳红包
pair<int,long long > best[maxn];
//dp(i,j) i位置被打扰了j次能获得的最少硬币
long long dp[maxn][205];
//寻找best的临时set容器
multiset<pair <int,long long > > now;
long long n,m,k;
void tclear()
{
memset(dp,-1,sizeof(dp));
for(long long i=0; i<=n+1; i++)
in[i].clear(),out[i].clear();
}
long long dfs(long long place, long long c)
{
if(place >n )
return 0;
if(dp[place][c]>=0)
return dp[place][c];
long long res=best[place].first+dfs(best[place].second+1,c);
if(c<m)
res=min(res,dfs(place+1,c+1));
return dp[place][c]=res;
}
int main()
{
while(cin>>n>>m>>k)
{
tclear();
long long l,r,d,w;
for(long long i=0; i<k; i++)
{
cin>>l>>r>>d>>w;
in[l].push_back(make_pair(w,d) );
out[r+1].push_back(make_pair(w,d) );
}
for(long long i=1; i<=n+1; i++)
{
for(long long j=0; j<in[i].size(); j++)
now.insert(in[i][j]); //加入可以领取的红包
for(long long j=0; j<out[i].size(); j++)
now.erase( now.find(out[i][j]) );//去掉不可取的,去掉单个不可取。如果now.erase(out[i][j]) 则删除所有相同的out[i][j];
if(now.size() )
best[i]=*now.rbegin();//选择最佳策略
else
best[i]= {(long long )0,(long long) i};
}
cout<<dfs(1,0)<<endl;
}
}
所以 multiset 嵌套pair 应该是 首先按照first 然后按照second排序
代码等同于
#include <bits/stdc++.h>
using namespace std;
const int maxn= 1e5+5;
struct node
{
int first,second;
//node(){}
node(int xx=0,int yy=0)
{
first=xx;
second=yy;
}
};
struct cmp
{
bool operator () (const node &a, const node &b)
{
if(a.first!=b.first)
return a.first<b.first;
else
return a.second<b.second;
}
};
//in 为可选红包,out为不可选红包
vector<node > in[maxn],out[maxn];
//代表每个时刻的最佳红包
node best[maxn];
//dp(i,j) i位置被打扰了j次能获得的最少硬币
long long dp[maxn][205];
//寻找best的临时set容器
multiset<node,cmp > now;
long long n,m,k;
void tclear()
{
memset(dp,-1,sizeof(dp));
for(long long i=0; i<=n+1; i++)
in[i].clear(),out[i].clear();
}
long long dfs(long long place, long long c)
{
if(place >n )
return 0;
if(dp[place][c]>=0)
return dp[place][c];
long long res=best[place].first+dfs(best[place].second+1,c);
if(c<m)
res=min(res,dfs(place+1,c+1));
return dp[place][c]=res;
}
int main()
{
while(cin>>n>>m>>k)
{
tclear();
long long l,r,d,w;
for(long long i=0; i<k; i++)
{
cin>>l>>r>>d>>w;
in[l].push_back(node(w,d) );
out[r+1].push_back(node(w,d) );
}
for(long long i=1; i<=n+1; i++)
{
for(long long j=0; j<in[i].size(); j++)
now.insert(in[i][j]); //加入可以领取的红包
for(long long j=0; j<out[i].size(); j++)
now.erase( now.find(out[i][j]) );//去掉不可取的,去掉单个不可取。如果now.erase(out[i][j]) 则删除所有相同的out[i][j];
if(now.size() )
best[i]=*now.rbegin();//选择最佳策略
else
best[i]= {(long long )0,(long long) i};
}
cout<<dfs(1,0)<<endl;
}
}