Contest:http://codeforces.com/contest/1106
也是隔了好久的题了,最近整理一波。差了一道,看情况写写吧。
A. Lunar New Year and Cross Counting(暴力判断)
题目链接:http://codeforces.com/contest/1106/problem/A
题目大意:找一个图中有多少个
X.X .X. X.X
形状的局部图。
思路:图的大小是500*500,直接暴力就好了。
ACCode:
const int MAXN=5e2+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll mod=1e9+7;
const double PI=acos(-1.0);
char mp[MAXN][MAXN];
int main(){
int n;
while(cin>>n){
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
cin>>mp[i][j];
}
}
int ans=0;
for(int i=2;i<n;++i){
for(int j=2;j<n;++j){
if(mp[i][j]=='X'){
if(mp[i-1][j+1]==mp[i][j]&&mp[i-1][j-1]==mp[i][j]
&& mp[i+1][j+1]==mp[i][j]&&mp[i+1][j-1]==mp[i][j]){
ans++;
}
}
}
}
cout<<ans<<endl;
}
}
B. Lunar New Year and Food Ordering(模拟)
题目链接:http://codeforces.com/contest/1106/problem/B
题目大意:一个餐馆有n种菜品,有m个顾客依次就餐,然后。输入n个菜品的数量和单价。之后m行,每行输入一个顾客的点菜和点菜数量。
顾客只有在吃完所有的菜之后才会付钱,否则就不会付钱。如果顾客要求的菜品不够,那么将从最便宜的菜品中选。(顾客吃菜之后,菜的数量会减少),问每个顾客的花费。
思路:首先按价格排序,然后模拟即可。加一个标记k,表示k菜品之前的所有菜品都没有了。
ACCode:
const int MAXN=1e5+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll mod=1e9+7;
const double PI=acos(-1.0);
struct node{
int id;
ll num,cost;
}arr[MAXN];
ll num[MAXN],cost[MAXN];
int cmp(node a,node b){
if(a.cost==b.cost)
return a.num<b.num;
return a.cost<b.cost;
}
int main(){
int n,m;
while(cin>>n>>m){
for(int i=1;i<=n;++i){
cin>>num[i];
}
for(int i=1;i<=n;++i){
cin>>cost[i];
}
for(int i=1;i<=n;++i){
arr[i]={i,num[i],cost[i]};
}sort(arr+1,arr+1+n,cmp);
ll need,kind,speed,k=1;
while(m--){
cin>>kind>>need;
speed=0;
if(num[kind]>=need){
num[kind]-=need;
speed=need*cost[kind];
cout<<speed<<endl;
continue;
}
else if(num[kind]>0){
need-=num[kind];
speed+=num[kind]*cost[kind];
num[kind]=0;
}
for(int i=k;i<=n;++i){
k=i;
if(num[arr[i].id]==0) continue;
if(num[arr[i].id]>=need){
num[arr[i].id]-=need;
speed+=need*cost[arr[i].id];
need=0;break;
}
else{
need-=num[arr[i].id];
speed+=num[arr[i].id]*cost[arr[i].id];
num[arr[i].id]=0;
}
}
if(need>0) speed=0;
cout<<speed<<endl;
}
}
}
C. Lunar New Year and Number Division(规律)
题目链接:http://codeforces.com/contest/1106/problem/C
题目大意:给你n个数,让你从中两两选择组成一些数,满足最小。输出这个数。
思路:很明显的规律,拍一下序,然后最前面的和最后面的两两组合。(题目保证输入数据为偶数个)。
ACCode:
const int MAXN=3e5+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll mod=1e9+7;
const double PI=acos(-1.0);
ll arr[MAXN];
int main(){
int n;
while(cin>>n){
for(int i=1;i<=n;++i){
cin>>arr[i];
}
sort(arr+1,arr+1+n);
ll ans=0;
for(int i=1;i<=n/2;++i)
ans+=(arr[i]+arr[n-i+1])*(arr[i]+arr[n-i+1]);
cout<<ans<<endl;
}
}
D. Lunar New Year and a Wander(规律,BFS)
题目链接:http://codeforces.com/contest/1106/problem/D
题目大意:给出一个图,从节点1开始。找出遍历这个图的字典序最小的路线(重复的走的节点只记录第一次经过的位置)。
思路:建好图之后直接搜索就好了。因为重复经过的节点记录一次就不记录了。因此BFS,每次找字典序最小的那个点就好了
ACCode:
const int MAXN=1e5+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll mod=1e9+7;
const double PI=acos(-1.0);
struct cmp{
bool operator()(const int &a,const int &b){
return a>b;
}
};
vector<int> vec[MAXN];
priority_queue<int,vector<int>,cmp> que;
int vis[MAXN];
int n,m;
void bfs(){
clean(vis,0);
while(que.size()) que.pop();
que.push(1);
vis[1]=1;
while(que.size()){
int e=que.top();que.pop();
cout<<e<<" ";
int len=vec[e].size();
for(int i=0;i<len;++i){
if(vis[vec[e][i]]==0){
que.push(vec[e][i]);
vis[vec[e][i]]=1;
}
}
}cout<<endl;
}
int main(){
while(cin>>n>>m){
for(int i=1;i<MAXN;++i){
vec[i].clear();
}
int a,b;
for(int i=1;i<=m;++i){
cin>>a>>b;
vec[a].push_back(b);
vec[b].push_back(a);
}
bfs();
}
}
E. Lunar New Year and Red Envelopes(思维,扫描线,DP,)
题目链接:http://codeforces.com/contest/1106/problem/E
题目大意:有长度为n的时间段,m次打扰,k个红包。每个红包有到达时间,消失时间,收集僵直时间(收集完这个红包之后di时间内不能收集红包了),和价值。在一个时间点上,如果有多个红包,一定会取最大的那个金额的红包。每次干扰的时候(设干扰时间点为x),Bob就在这个时间点无法收取红包,但在x+1时刻就可以收取红包了。我们想用少于m此机会使得Bob收集的红包金额最小,问最小是多少?
思路:一看题,就知道是一个很明显的动态规划问题。
首先得出Bob所能获得的红包的最大价值。可以用扫描线来获得。扫描时间点,每个时间点都进行比较。
然后,对于每个时间点,我们可以选择干扰||不干扰,转换成动态规划问题。
状态转移方程:对于j次打扰。
f[j+1][i+1]=min(f[j+1][i+1],f[j][i]);
f[j][a[i].d+1]=min(f[j][a[i].d+1],f[j][i]+a[i].w);
因为n*m比较大,因此用滚动数组来优化。
ACCode:
// luogu-judger-enable-o2
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<string>
#include<fstream>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define Pair pair<int,int>
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))// ˮӡ
//std::ios::sync_with_stdio(false);
// register
const int MAXN=1e5+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const int MOD=1e9+7;
const double EPS=1.0e-8;
const double PI=acos(-1.0);
struct node{
int d,w,t;
bool operator <(const node &e)const {
return w>e.w||(w==e.w&&d>e.d);
}
};
vector<node> e[MAXN];
node a[MAXN];
map<node,int> cur;
ll f[2][MAXN],ans=INF64;
int n,m,k;
void Insert(node x){
if(cur.count(x)) cur[x]++;
else cur[x]=1;
}
void Erase(node x){
cur[x]--;
if(cur[x]==0) cur.erase(x);
}
int main(){
scanf("%d%d%d",&n,&m,&k);
int s,t,d,w;
for(int i=1;i<=k;++i){
scanf("%d%d%d%d",&s,&t,&d,&w);
e[s].push_back(node{d,w,1});
e[t+1].push_back(node{d,w,-1});
}
for(int i=1;i<=n;++i){
for(int it=0;it<e[i].size();++it){
if(e[i][it].t==1) Insert(e[i][it]);
else Erase(e[i][it]);
}
if(cur.size()) a[i]=(*(cur.begin())).first;//这个时间点有红包
else a[i]=node({i,0,0});//没有红包
}clean(f,0x3f);
f[0][1]=0;
for(int j=0;j<=m;++j){
clean(f[(j^1)&1],0x3f);
for(int i=1;i<=n;++i){
f[(j^1)&1][i+1]=min(f[(j^1)&1][i+1],f[j&1][i]);
f[j&1][a[i].d+1]=min(f[j&1][a[i].d+1],f[j&1][i]+a[i].w);
}ans=min(ans,f[j&1][n+1]);
}printf("%lld\n",ans);
}