08-19考试总结
08-19考试总结
今天状态还可以
0819秘密通道 (portal)
- 是一个玄学建图 \(+\) 最短路
- 可惜考场上没想出来建图
- 对于图上每一个点,我们将它与它上下左右方向能用子弹打到的地方连边
- 然后对它相邻的点也正常连边,跑一边最短路
/*************************************************************************
> File Name: portal.cpp
> Author: Typedef
> Mail: 1815979752@qq.com
> Created Time: 2021-08-19 17:09:33
> blog: https://www.cnblogs.com/Illyasviel
************************************************************************/
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int N=5e2+7;
int n,m,a,b;
int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
int d[N*N];
char s[N][N];
bool vis[N*N];
vector<pair<int,int> > son[N*N];
int getid(int x,int y){
return m*(x-1)+y;
}
void add(int a,int b,int c){
son[a].push_back(make_pair(b, c));
}
template<class T>void qread(T &x){
x=0;bool f=0;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48);c=getchar();}
if(f) x=-x;
}
void buildmap(int x,int y){
if(s[x][y]=='#') return;
int a,b,c,d;
int u=getid(x,y),w=INF;
for(int i=x;i<=n;i++)
if(s[i][y]=='#'){
a=getid(i-1,y),w=min(w,i-x);
break;
}
for(int i=x;i;i--)
if(s[i][y]=='#'){
b=getid(i+1,y),w=min(w,x-i);
break;
}
for(int i=y;i<=m;i++)
if(s[x][i]=='#'){
c=getid(x,i-1),w=min(w,i-y);
break;
}
for(int i=y;i;i--)
if(s[x][i]=='#'){
d=getid(x,i+1),w=min(w,y-i);
break;
}
add(u,a,w),add(u,b,w),add(u,c,w),add(u,d,w);
return;
}
void connect(int ux,int uy,int vx,int vy){
if(s[vx][vy]=='#') return;
add(getid(ux,uy),getid(vx,vy),1);
}
queue<int> q;
void SPFA(int s){
memset(d,0x3f,sizeof(d));
d[s]=0;
q.push(s);
vis[s]=true;
while(!q.empty()){
int u=q.front();
vis[u]=0;
q.pop();
for(unsigned int i=0;i<son[u].size();i++){
int v=son[u][i].first,w=son[u][i].second;
if(d[u]+w<d[v]){
d[v]=d[u]+w;
if(!vis[v]) q.push(v),vis[v]=1;
}
}
}
return;
}
int main(){
qread(n),qread(m);
for(int i=1;i<= n;i++) scanf("%s",s[i]+1);
for(int i=2;i<n;i++)
for(int j=2;j<m;j++){
if(s[i][j]=='#') continue;
for(int k=0;k<4;k++){
int x=i+dx[k],y=j+dy[k];
buildmap(i,j);
connect(i,j,x,y);
}
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
if(s[i][j]=='C') a=getid(i,j);
if(s[i][j]=='F') b=getid(i,j);
}
SPFA(a);
if(d[b]==INF) puts("nemoguce");
else printf("%d\n",d[b]);
return 0;
}
0819购物 (shopping)
- 嗯,怎么说呢,是一个带有一点反悔功能的贪心
- 首先,如果你手上的钱不多,连优惠后都卖不够前 \(k\) 个最便宜的,那么就尽量多的卖就行了
- 然后,如果你买了前 \(k\) 个折后最便宜的,手上还有钱剩下的话,那就先把剩下的按原价排序
- 然后,把你前 \(k\) 个打过折的,按照省钱的多少,丢到小根堆里
- 每次去除最不能省钱的,把他换成你这个最便宜的试试看,是否能更新答案
/*************************************************************************
> File Name: portal.cpp
> Author: Typedef
> Mail: 1815979752@qq.com
> Created Time: 2021-08-19 07:32:30
> blog: https://www.cnblogs.com/Illyasviel
************************************************************************/
#include<bits/stdc++.h>
#define INF 0x7fffffff
using namespace std;
typedef long long ll;
const int N=5e4+7;
template<class T>void qread(T &x){
x=0;bool f=0;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48);c=getchar();}
if(f) x=-x;
}
ll n,m,k,res;
struct Node{
ll p,q;
friend bool operator<(const Node &a,const Node &b){
return a.q<b.q;
}
}a[N];
ll ori[N];
ll cnt=0,pos=0,idx=0,j=0;
priority_queue<ll,vector<ll>,greater<ll> > q;
int main(){
qread(n),qread(k),qread(m);
for(int i=1;i<=n;i++){
ll x,y;
qread(x),qread(y);
a[i]={x,y};
}
res=m;
sort(a+1,a+n+1);
for(int i=k+1;i<=n;i++) ori[++idx]=a[i].p;
for(int i=1;i<=k;i++){
if(res>=a[i].q){
res-=a[i].q,cnt++,pos=i;
q.push(a[i].p-a[i].q);
}
else break;
}
if(pos!=k){
printf("%lld\n",cnt);
return 0;
}
j=1,pos++;
sort(ori+1,ori+idx+1);
while(res>=0&&(j<=idx||pos<=n)){
ll pnow=q.top();
ll pmin=min(ori[j],a[pos].q+pnow);
if(res>=pmin){
if(pmin==ori[j]){
res-=ori[j];
cnt++,j++;
if(j>idx) ori[j]=INF;
if(cnt==n) break;
}
else{
q.pop();
res-=a[pos].q+pnow,cnt++;
q.push(a[pos].p-a[pos].q);
pos++;
}
}
else break;
}
printf("%lld\n",cnt);
return 0;
}
0819拆网线 (tree)
- 看题目的要求,发现一个类似匹配的东西能使答案最优
- 于是我就跑了个树形DP
f[i][1/0]表示在 \(i\) 点选或不选的情况下,需要保留网线的数量- 不过据说有一种贪心做法,从树的底部开始往上放,放到不能放为止
- 也有人写的其他做法
/*************************************************************************
> File Name: portal.cpp
> Author: Typedef
> Mail: 1815979752@qq.com
> Created Time: 2021-08-19 07:32:30
> blog: https://www.cnblogs.com/Illyasviel
************************************************************************/
#include<bits/stdc++.h>
#define INF 0x7fffffff
using namespace std;
typedef long long ll;
const int N=5e4+7;
template<class T>void qread(T &x){
x=0;bool f=0;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48);c=getchar();}
if(f) x=-x;
}
ll n,m,k,res;
struct Node{
ll p,q;
friend bool operator<(const Node &a,const Node &b){
return a.q<b.q;
}
}a[N];
ll ori[N];
ll cnt=0,pos=0,idx=0,j=0;
priority_queue<ll,vector<ll>,greater<ll> > q;
int main(){
qread(n),qread(k),qread(m);
for(int i=1;i<=n;i++){
ll x,y;
qread(x),qread(y);
a[i]={x,y};
}
res=m;
sort(a+1,a+n+1);
for(int i=k+1;i<=n;i++) ori[++idx]=a[i].p;
for(int i=1;i<=k;i++){
if(res>=a[i].q){
res-=a[i].q,cnt++,pos=i;
q.push(a[i].p-a[i].q);
}
else break;
}
if(pos!=k){
printf("%lld\n",cnt);
return 0;
}
j=1,pos++;
sort(ori+1,ori+idx+1);
while(res>=0&&(j<=idx||pos<=n)){
ll pnow=q.top();
ll pmin=min(ori[j],a[pos].q+pnow);
if(res>=pmin){
if(pmin==ori[j]){
res-=ori[j];
cnt++,j++;
if(j>idx) ori[j]=INF;
if(cnt==n) break;
}
else{
q.pop();
res-=a[pos].q+pnow,cnt++;
q.push(a[pos].p-a[pos].q);
pos++;
}
}
else break;
}
printf("%lld\n",cnt);
return 0;
}
0819密室 (room)
- 状压 \(+\) bfs转移
- 把当前的钥匙持有情况压缩到状态里
f[i][j]表示当前钥匙持有情况为 \(i\) ,到达 \(j\) 点,所用的最少传送门的数量
/*************************************************************************
> File Name: room.cpp
> Author: Typedef
> Mail: 1815979752@qq.com
> Created Time: 2021-08-19 10:04:22
> blog: https://www.cnblogs.com/Illyasviel
************************************************************************/
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int N=6e3+7;
int d[N];
bool vis[1<<11][N];
int h[N],e[N<<1],ne[N<<1],key[N<<1];
int st[N];
int f[1<<11][N];
int idx=0;
int n,m,k;
void add(int a,int b,int c){
e[idx]=b;
ne[idx]=h[a];
key[idx]=c;
h[a]=idx++;
}
struct Node{
int u,key;
};
queue<Node> q;
template<class T>void qread(T &x){
x=0;bool f=0;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48);c=getchar();}
if(f) x=-x;
}
int ans=INF;
int main(){
memset(h,-1,sizeof(h));
qread(n),qread(m),qread(k);
for(int i=1;i<=n;i++)
for(int j=1;j<=k;j++){
int x;
qread(x);
st[i]<<=1,st[i]+=x;
}
for(int i=1;i<=m;i++){
int K=0,x,y;
qread(x),qread(y);
for(int j=1;j<=k;j++){
int X;
qread(X);
K<<=1;
K+=X;
}
add(x,y,K);
}
memset(f,0x3f,sizeof(f));
f[st[1]][1]=0;
vis[st[1]][1]=1;
q.push({1,st[1]});
while(!q.empty()){
int u=q.front().u,ukey=q.front().key;
q.pop();
vis[ukey][u]=false;
for(int i=h[u];~i;i=ne[i]){
int v=e[i];
int vkey=ukey|st[v];
if((key[i]&ukey)==key[i]&&f[vkey][v]>f[ukey][u]+1){
f[vkey][v]=f[ukey][u]+1;
if(!vis[vkey][v]) vis[vkey][v]=true,q.push({v,vkey});
}
}
}
for(int i=0;i<(1<<k);i++) ans=min(ans,f[i][n]);
if(ans==INF) puts("No Solution");
else printf("%d\n",ans);
return 0;
}

浙公网安备 33010602011771号