题意:题目是说从0到n-1,我还是习惯从1到n,所以以下我都这么写,大概题意就是(i, j)==‘Y’表示可以从i颜色变成j颜色,然后问我们最少删除几个会影响结果的‘Y’,能到n这个颜色;
没有意义的‘Y’:因为题目说了,能变色就一定得变色,而且,每次变色都得变成当前能变的颜色最小的那个,所有有可能执行了某些变色操作会导致变不成n,比如n==4,(1,2)==‘Y’;(3,4)==‘Y’;
那么会先变成2,然后就没得变了;
解题思路:
#include<iostream> #include<algorithm> #include<string> #include<queue> #include<cstring> #define maxn 10005 #define inf 0x3f3f3f3f using namespace std; struct node { int num; int dist; node(int _num=0,int _dist=0):num(_num),dist(_dist){} friend bool operator<(node a,node b) { return a.dist>b.dist; } }; struct Edge { int next; int to; int w; }edge[maxn]; int head[maxn]; int dist[maxn]; int cnt; int visit[maxn]; void add(int u,int v,int w) { edge[cnt].next=head[u]; edge[cnt].w=w; edge[cnt].to=v; head[u]=cnt++; } void dij(int x) { priority_queue<node>que; memset(dist,0x3f3f3f3f,sizeof(dist)); memset(visit,0,sizeof(visit)); dist[x]=0; que.push(node(x,0)); while(!que.empty()) { node u=que.top(); que.pop(); int now=u.num; for(int i=head[now];i!=-1;i=edge[i].next) { Edge e=edge[i]; if(dist[e.to]>dist[now]+e.w) { dist[e.to]=dist[now]+e.w; que.push(node(e.to,dist[e.to])); } } } } int main() { char s[60][60]; int t; int n; cin>>t; while(t--) { cin>>n; memset(head,-1,sizeof(head));cnt=0; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) cin>>s[i][j]; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { int cnt=0; if(s[i][j]=='Y') { for(int k=1;k<=j-1;k++) { if(s[i][k]=='Y') cnt++; } add(i,j,cnt); } } } dij(1); if(dist[n]==inf) cout<<"-1\n"; else cout<<dist[n]<<endl; } return 0; }
根据先变小的这个操作,所以,我们可以这么建图,(i,j)==‘Y’时,可以建一条从i到j的边,权值为第i行开始从[1,j-1]中‘Y'的数量,因为如果我们要用这条边的话,因为先变小,所以我们得把这一行中比当前小的都删去,删掉一个权值加1;
代码: