思路:这是一道十分骚的题目…首先,我也不知道我的暴力bfs只有20分…然而实际是爆零的——格式错误(输出一行,最后没空格且有换行T_T)。
正解也是挺简单的,预处理每个点两次dfs就够了,第1次dfs染色+找边界,
第2次算步数。
code:
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;i++)
#define DREP(i,f,t) for(int i=(f),i##_end_=(t);i>=i##_end_;i--)
#define LL long long
#define db double
#define INF 0x3f3f3f3f
#define inf 0x7fffffff
#define pb push_back
#define Sz(a) sizeof(a)
#define mcl(a,b) memset(a,b,Sz(a))
#define mcp(a,b) memcpy(a,b,Sz(b))
#define N 1005
int n,m,ans;
int A[N][N];
int dx[]={-1,-1,-1,0,0,1,1,1};
int dy[]={-1,0,1,-1,1,-1,0,1};
bool check(int x,int y){return x<0 || x>n || y<0 || y>n;}
bool check_done(int x,int y){return x==1 || x==n || y==1 || y==n;}
struct p40{
struct node{
int x,y,step;
};
bool vis[N][N];
int bfs(int sx,int sy){
queue Q;
while(!Q.empty())Q.pop();
Q.push((node){sx,sy,0});
int ans=INF;
while(!Q.empty()){
node now=Q.front();Q.pop();
if(check_done(now.x,now.y)){
ans=min(ans,now.step);
continue;
}
REP(i,0,7){
int nx=now.x+dx[i];
int ny=now.y+dy[i];
if(check(nx,ny))continue;
if(vis[nx][ny])continue;
vis[nx][ny]=1;
node nxt;
nxt.x=nx,nxt.y=ny,nxt.step=now.step;
if(A[nx][ny]==1 && A[now.x][now.y]==0)nxt.step++;
Q.push(nxt);
}
}
return ans;
}
void solve(){
REP(i,1,m){
int x,y;
scanf("%d%d",&x,&y);
memset(vis,0,Sz(vis));
printf("%d",bfs(x,y));
if(i!=m)putchar(' ');
}
puts("");
}
}p40;
struct p100{
int mark[N][N];
int ans[N][N];
int Min;
void dfs(int x,int y,int col){
mark[x][y]=1;
if(x==1||x==n||y==1||y==n)Min=0;
REP(i,0,7){
int nx=dx[i]+x,ny=dy[i]+y;
if(check(nx,ny))continue;
if(ans[nx][ny]!=-1)Min=min(Min,ans[nx][ny]+(A[nx][ny]==1 && A[x][y]==0));
if(mark[nx][ny]!=0 || A[x][y]!=A[nx][ny])continue;
dfs(nx,ny,col);
}
}
void Dfs(int x,int y){
ans[x][y]=Min;
mark[x][y]=-1;
REP(i,0,7){
int nx=dx[i]+x,ny=dy[i]+y;
if(mark[nx][ny]!=1)continue;
Dfs(nx,ny);
}
}
void solve(){
mcl(ans,-1);
REP(i,1,n){
REP(j,1,n){
if(mark[i][j])continue;
Min=INF;
dfs(i,j,A[i][j]);
Dfs(i,j);
}
}
REP(i,1,m){
int a,b;
scanf("%d%d",&a,&b);
printf("%d",ans[a][b]);
if(i!=m)putchar(' ');
}
puts("");
}
}p100;
char s[N];
int main(){
// freopen("river.in","r",stdin);
// freopen("river.out","w",stdout);
// printf("%d\n",(Sz(p100)+Sz(p40))/1024/1024);
cin>>n>>m;
REP(i,1,n){
scanf("%s",s+1);
REP(j,1,n)A[i][j]=(s[j]=='1');
}
if(n<=10)p40.solve();
else p100.solve();
return 0;
}
思路:暴力30;
正解应该是计算出每个颜色对每个格子的贡献,
据题意知,颜色只有出现1次才有用,也就是说第2次出现时没用的,
那么就可以根据上一次该颜色出现的位置和当前颜色出现的位置,那么贡献的长度为posj-posi,len应该是扫描时加过来的。
但最后还有第一次和第二之间的答案没有累加,最后再扫描一遍补上。
code:
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;i++)
#define DREP(i,f,t) for(int i=(f),i##_end_=(t);i>=i##_end_;i--)
#define LL long long
#define db double
#define INF 0x3f3f3f3f
#define inf 0x7fffffff
#define pb push_back
#define Sz(a) sizeof(a)
#define mcl(a,b) memset(a,b,Sz(a))
#define mcp(a,b) memcpy(a,b,Sz(b))
#define N 1105
#define P 19900907
int n,m;
struct p30{
int A[N][N];
LL ans;
int cnt[105];
void work(int x,int y){
mcl(cnt,0);
REP(i,1,x)REP(j,1,y)cnt[A[i][j]]++;
REP(i,0,100)if(cnt[i]==1)ans++,ans%=P;
}
void solve(){
REP(i,1,n)REP(j,1,m)scanf("%d",&A[i][j]);
ans=0;
REP(i,1,n)
REP(j,1,m)
work(i,j);
cout<struct p100{
int pos1[N*N],pos2[N*N],len[N*N];
void solve(){
LL ans=0;
REP(i,1,n)REP(j,1,m){
int col;scanf("%d",&col);
if(!len[col]){
len[col]=i;
pos1[col]=j;
pos2[col]=m+1;
continue;
}
if (j1LL*(i-len[col])*(pos2[col]-pos1[col])%P,ans%=P;
pos2[col]=pos1[col];
pos1[col]=j;
len[col]=i;
} else if (j1LL*(i-len[col])*(pos2[col]-j)%P,ans%=P;
pos2[col]=j;
}
}
REP(i,1,n*m)if(len[i])ans+=1LL*(n+1-len[i])*(pos2[i]-pos1[i])%P,ans%=P;
cout<int main(){
// freopen("resource.in","r",stdin);
// freopen("resource.out","w",stdout);
// printf("%d\n",(Sz(A)+Sz(p100)+Sz(p30))/1024/1024);
cin>>n>>m;
if(n<=100 && m<=100)p30.solve();
else p100.solve();
return 0;
}
思路:这是一道十分水的最短路题…
题意是算出最小时间,但是根据题意知道,最短路还不够,还要去一个城市的结界城市,并走到那;
也就是说,ans=max(dis[n],炸掉n的结界城市的最迟时间)。
而dis[i]又会被城市i的结界城市所影响,所以另外应该记录到i的最迟时间。
最后就是通过Dijkstra跑最短路即可。
code:
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;i++)
#define DREP(i,f,t) for(int i=(f),i##_end_=(t);i>=i##_end_;i--)
#define LL long long
#define db double
#define INF 0x3f3f3f3f
#define inf 1e15
#define pb push_back
#define Sz(a) sizeof(a)
#define mcl(a,b) memset(a,b,Sz(a))
#define mcp(a,b) memcpy(a,b,Sz(b))
#define N 3005
int n,m;
int num[N];
struct node{
int to;
LL cost;
bool operator <(const node &_) const{
return cost>_.cost;
}
};
vector E[N];
vector<int>G[N];
priority_queueQ;
LL dis[N],d[N][2];
bool vis[N];
void Dijkstra(){
REP(i,1,n)dis[i]=d[i][0]=d[i][1]=inf;
REP(i,1,n)if(!num[i])d[i][1]=0;
d[1][0]=0;dis[1]=0;
Q.push((node){1,0});
while(!Q.empty()){
node q=Q.top();
Q.pop();
int x=q.to;
if(vis[x])continue;
vis[x]=1;
REP(i,0,G[x].size()-1){
int y=G[x][i];num[y]--;
if(d[y][1]==inf)d[y][1]=dis[x];
else d[y][1]=max(d[y][1],dis[x]);
dis[y]=max(d[y][1],d[y][0]);
if(!num[y]&&dis[y]!=inf)Q.push((node){y,dis[y]});
}
REP(i,0,E[x].size()-1){
int y=E[x][i].to;
if(vis[y])continue;
if(d[y][0]>dis[x]+E[x][i].cost && !num[y]){
d[y][0]=dis[x]+E[x][i].cost;
LL t=max(d[y][0],d[y][1]);
if(dis[y]>t){
dis[y]=t;
Q.push((node){y,dis[y]});
}
}
else if(d[y][0]>dis[x]+E[x][i].cost)d[y][0]=dis[x]+E[x][i].cost;
}
}
}
int main(){
// freopen("landcraft.in","r",stdin);
// freopen("landcraft.out","w",stdout);
cin>>n>>m;
REP(i,1,m){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
E[a].push_back((node){b,c});
}
REP(i,1,n){
int x;
scanf("%d",&num[i]);
REP(j,1,num[i])scanf("%d",&x),G[x].push_back(i);
}
Dijkstra();
printf("%lld\n",dis[n]);
return 0;
}
小结:第1题的题目着实坑…简直无解爆零…第2题最后ans没有mod…
还是有一大堆低级错误——考试时应该将note就放在代码旁边…