NOIP 2011 Day 1
tags:
- NOIP
- 搜索
categories: - 信息学竞赛
- 总结
铺地毯
Solution
因为只会询问一个点被谁覆盖, 而且后面的地毯会覆盖前面的地毯, 所以只需要从后往前枚举地毯, 只要能覆盖这个点就是最终覆盖它的地毯.
Code
#include<iostream>
#include<cstdio>
using namespace std;
int x[10005];
int y[10005];
int a[10005];
int b[10005];
int main(){
int n;
cin>>n;
for(int i=1;i<=n;++i)
cin>>x[i]>>y[i]>>a[i]>>b[i];
int p,q;
cin>>p>>q;
for(int i=n;i;--i)
if(p>=x[i]&&q>=y[i])
if(x[i]+a[i]>=p&&y[i]+b[i]>=q){
cout<<i;
return 0;
}
cout<<-1;
return 0;
}
选择客栈
Solution
选择链表, 依次从后枚举每种色调的旅馆, 因为链表本来就是从后往前遍历的, 然后枚举色调相同的前一个宾馆, 如果满足要求, 那么它前面的所有宾馆都满足要求.如果快速判断只要求出一个点其靠后的花费满足要求的最前一个点即可.这个可以通过递推得到.
而且这个链表的复杂度实际上比较玄学的, 理论最高复杂度为\(O(n^2)\), 但是一般不会达到.而且他实际上比最优解只慢几倍.并不知道最优解释什么……
Code
#include<iostream>
#include<cstdio>
#define N 200005
#define inf 0x3f3f3f3f
using namespace std;
struct Edge{
int v,nxt;
}e[N];
int head[N],tot;
int n,k,p;
int c[N];
int f[N];
int count[N];
int kth[N];
void AddEdge(int pos,int u){
e[++tot]=(Edge){pos,head[u]};head[u]=tot;
}
int a,b;
int main(){
cin>>n>>k>>p;
for(int i=1;i<=n;++i){
scanf("%d%d",&b,&a);c[i]=a;
AddEdge(i,b);
}
for(int i=0;i<k;++i){
int sum=0;
for(int j=head[i];j;j=e[j].nxt)
kth[e[j].v]=sum,++sum;
count[i]=sum;
}
f[n]=inf;
long long ans=0;
if(c[n]<=p)f[n]=n;
for(int i=n-1;i>=1;--i){
if(c[i]<=p)f[i]=i;
else f[i]=f[i+1];
}
int p2,p3;
for(int i=k-1;i>-1;--i){
p2=head[i];
for(;p2;p2=e[p2].nxt){
for(p3=e[p2].nxt;p3;p3=e[p3].nxt){
if(e[p2].v>e[p3].v&&f[e[p3].v]<=e[p2].v){
ans+=count[i]-kth[e[p3].v];
break;
}
}
}
}
printf("%lld",ans);
return 0;
}
Mayan游戏
Solution
这应该是这三个题中最容易看出做法的题, 但是并不是很好写.写到100行到200行之间还是比较正常的.
看见一个写的比较漂亮的(封装的比较好).并非一日之功, 改天练好本领再来挑战你吧!
#include<cstdio>
#include<cstring>
#include<iostream>
#include<map>
#include<stack>
using namespace std;
struct board{
int p[5][7];
inline void read();
inline void down(int line){
for(int i(1);i<7;++i){
if(!p[line][i])continue;
int pos(i);
while(!p[line][pos-1]&&pos>0){
p[line][pos-1]=p[line][pos];
p[line][pos]=0;
--pos;
}
}
}
inline bool empty(){
for(int i(0);i<5;++i)if(p[i][0])return false;
return true;
}
inline void swap(int x1,int y1,int x2,int y2){
if(p[x1][y1]==p[x2][y2])return;
p[x1][y1]^=p[x2][y2];
p[x2][y2]^=p[x1][y1];
p[x1][y1]^=p[x2][y2];
if(!p[x1][y1]||!p[x2][y2])
down(x1),down(x2);
}
inline bool clear(){
bool cls[5][7];
bool k(false);
for(int i(0);i<5;++i)
for(int j(0);j<7;++j)
cls[i][j] = false;
for(int i(0);i<5;++i){
int now(0);
for(int j(1);j<7;++j){
if(!p[i][j])break;
if(p[i][j]!=p[i][now]){now=j;continue;}
if(j-now==2){k=true;for(int k(now);k<=j;++k)cls[i][k]=true;}
if(j-now>2)cls[i][j]=true;
}
}
for(int i(0);i<7;++i){
int now(0);
for(int j(1);j<5;++j){
if(p[j][i]==0){now=j+1;continue;}
if(p[j][i]!=p[now][i]){now=j;continue;}
if(j-now==2){k=true;for(int k(now);k<=j;++k)cls[k][i]=true;}
if(j-now>2)cls[j][i]=true;
}
}
if(!k)return false;
for(int i(0);i<5;++i){
bool e(false);
for(int j(0);j<7;++j)
if(cls[i][j])
e=true,p[i][j] = 0;
if(e)down(i);
}
return true;
}
bool operator<(const board &a)const{
for(int i(0);i<5;++i)
for(int j(0);j<7;++j)
if(p[i][j]!=a.p[i][j])
return p[i][j]<a.p[i][j];
return false;
}
};
void board::read(){
memset(p,0,sizeof(p));
for(int i(0);i<5;++i){
for(int j(0);j<7;++j){
scanf("%d",&p[i][j]);
if(!p[i][j])break;
if(j==6)scanf("%*d");
}
}
}
stack<pair<pair<int,int>,int> > ans;
map <board,bool> used[10];
int n;
inline bool dfs(int step,board now){
if(n<step)return now.empty();
if(used[step][now])return false;
used[step][now]=1;
int tot[11];
memset(tot,0,sizeof(tot));
for(int i(0);i<5;++i)for(int j(0);j<7;++j)++tot[now.p[i][j]];
int i(0),j;
board tmp;
for(j=0;j<7;++j){
if(!now.p[0][j])break;
tmp=now;
tmp.swap(0,j,1,j);
while(tmp.clear());
if(dfs(step+1,tmp)){
ans.push(make_pair(make_pair(0,j),1));
return true;
}
}
for(int i(1);i<4;++i){
for(int j(0);j<7;++j){
if(!now.p[i][j])break;
tmp=now;
tmp.swap(i,j,i+1,j);
while(tmp.clear());
if(dfs(step+1,tmp)){
ans.push(make_pair(make_pair(i,j),1));
return true;
}
if(!now.p[i-1][j]){
tmp=now;
tmp.swap(i,j,i-1,j);
while(tmp.clear());
if(dfs(step+1,tmp)){
ans.push(make_pair(make_pair(i,j),-1));
return true;
}
}
}
}
for(int j(0);j<7;++j){
if(!now.p[4][j])break;
if(!now.p[3][j]){
tmp=now;
tmp.swap(4,j,3,j);
while(tmp.clear());
if(dfs(step+1,tmp)){
ans.push(make_pair(make_pair(4,j),-1));
return true;
}
}
}
return false;
}
int main(){
scanf("%d",&n);
board start;
start.read();
if(dfs(1,start)){
while(!ans.empty()){
pair<pair<int,int>,int> tmp;
tmp=ans.top();
printf("%d %d %d\n",tmp.first.first,tmp.first.second,tmp.second);
ans.pop();
}
}
else printf("-1\n");
return 0;
}