失分小結:
估分:160
實際分數:170
今天身體不舒服,第三題理所當然地爆零了搞起來狀態好就會寫一樣
前面兩題還過得去,該水的分都水到了,只是第二題的正解敲了半天沒調出來有些可惜還是代碼功底弱的原因
第一題:
感覺自己的寫法有些鬼畜瞎湊出答案
bfs+dfs,
bfs保證每步最優,dfs求聯通塊
struct node{int x,y,sp;};
queue<node>q;
int mp[1005][1005];
bool mark[1005][1005];
int step[1005][1005];
int n,m;
int cx[]={0,1,-1,0,1,1,-1,-1};
int cy[]={1,0,0,-1,1,-1,1,-1};
void dfs(int x,int y,int sp){
for(int i=0;i<8;i++){
int nx=x+cx[i],ny=y+cy[i];
if(nx<=0||ny<=0||nx>n||ny>n||mark[nx][ny])continue;
if(mp[nx][ny]!=mp[x][y])continue;
mark[nx][ny]=1;
dfs(nx,ny,sp);
q.push((node){nx,ny,sp});
}
}
void BFS(){
for(int i=1;i<=n;i++){
if(!mark[1][i]){
q.push((node){1,i,0});
mark[1][i]=1;
dfs(1,i,0);
}
if(!mark[1][n]){
q.push((node){1,n,0});
mark[1][n]=1;
dfs(1,n,0);
}
if(!mark[i][1]){
q.push((node){i,1,0});
mark[i][1]=1;
dfs(i,1,0);
}
if(!mark[n][i]){
q.push((node){n,i,0});
mark[n][i]=1;
dfs(n,i,0);
}
}
while(!q.empty()){
node now=q.front();q.pop();
int x=now.x,y=now.y;
step[x][y]=now.sp;
FOR(i,0,7){
int nx=x+cx[i],ny=y+cy[i];
if(!nx||!ny||nx>n||ny>n||mark[nx][ny])continue;
mark[nx][ny]=1;
if(!mp[x][y]){
dfs(nx,ny,now.sp);
q.push((node){nx,ny,now.sp});
}
else {
dfs(nx,ny,now.sp+1);
q.push((node){nx,ny,now.sp+1});
}
}
}
}
int main(){
scanf("%d%d",&n,&m);
FOR(i,1,n){
char C[1005];
scanf("%s",C+1);
FOR(j,1,n){
mp[i][j]=C[j]-'0';
}
}
BFS();
while(m--){
int x,y;
scanf("%d%d",&x,&y);
printf("%d ",step[x][y]);
}
puts("");
return 0;
}
突然發現這幾次較難的第一題都能被gang出來沾沾自喜
第二題:
這道題就比較正常了,
模擬可以水30分,然後優化就60分。然後考慮單點貢獻,對於每一個點
都可以算出包含它並使其有效的區間,然後記錄每一種顏色的有效範圍區間
以上思路由Isrothy給出
#include<bits/stdc++.h>
using namespace std;
#define FOR(i,x,y) for(int i=(x);i<=(y);i++)
#define DOR(i,x,y) for(int i=(x);i>=(y);i--)
#define P 19900907
#define M 1105
#define ll long long
bool mark[M*M];
struct node{int l,r;}T[M*M];
int main(){
int n,m,a;
ll ans=0;
scanf("%d%d",&n,&m);
FOR(i,1,n)FOR(j,1,m){
scanf("%d",&a);
if(!mark[a]){
ans+=(n-i+1)*(m-j+1);
ans%=P;
mark[a]=1;
T[a].l=j,T[a].r=m;
}
else {
if(j>T[a].r)continue;
if(T[a].l<=j&&j<=T[a].r){
ans-=(n-i+1)*(T[a].r-j+1);
ans%=P;
T[a].l=j;
}
else{
ans-=(m-j)*(n-i+1);
ans+=(T[a].l-j+1)*(n-i+1);
ans%=P;
T[a].r=T[a].l,T[a].l=j;
}
}
}
printf("%lld\n",(ans+P)%P);
return 0;
}
第三題沒有寫出來主要是因爲沒有很好地理解最短路算法當初模板全靠背
再算最短路的時候,我們可以得到到每個點的時間,然後當我們已經到達某點並一到達此點所需的其他點時,把它加進隊列中裸的模板題ni
#include<bits/stdc++.h>
using namespace std;
#define N 3005
struct node{
long long v;int to;
bool operator < (const node &_)const{
return v>_.v;
}
};
vector<int>Q[N];
vector<node>edge[N];
int degree[N];
bool haved[N];
long long dis[N];
void dij(int s){
memset(dis,-1,sizeof(dis));
priority_queue<node>q;
dis[s]=0;
q.push((node){0,s});
while(!q.empty()){
node now=q.top();q.pop();
if(dis[now.to]!=now.v)continue;
if(degree[now.to]){
haved[now.to]=1;
continue;
}
for(int i=0;i<(int)Q[now.to].size();i++){
int y=Q[now.to][i];
degree[y]--;
if(!degree[y]&&haved[y]){
q.push((node){now.v,y});
dis[y]=now.v;
}
}
for(int i=0;i<(int)edge[now.to].size();i++){
int y=edge[now.to][i].to;
if(dis[y]==-1||dis[now.to]+edge[now.to][i].v<dis[y]){
dis[y]=dis[now.to]+edge[now.to][i].v;
q.push((node){dis[y],y});
}
}
}
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int a,b;long long c;
scanf("%d%d%lld",&a,&b,&c);
edge[a].push_back((node){c,b});
}
for(int i=1;i<=n;i++){
int x,a;
scanf("%d",&x);
degree[i]=x;
for(int j=1;j<=x;j++){
scanf("%d",&a);
Q[a].push_back(i);
}
}
dij(1);
printf("%lld\n",dis[n]);
return 0;
}
距離NOIP還有2天 fighting!