1 条题解

  • 1
    @ 2022-8-26 9:57:26
    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <queue>
    #include <algorithm>
    #define ll long long
    using std::min;
    using std::vector;
    using std::priority_queue;
    using std::pair;
    using std::sort;
    typedef pair<int, int> pad;
    
    const int MAXN =5e2+5, MAXK =55;
    
    namespace IO_base{
    	const int MAXB =1<<10;
    	char gbuf[MAXB], *ps =gbuf, *pt =gbuf;
    	
    	char _getchar(){
    		if(ps == pt)
    			ps =gbuf, pt =gbuf+fread(gbuf, 1, MAXB, stdin);
    		return (ps == pt) ? EOF : *ps++;
    	}
    }
    #define getchar IO_base::_getchar
    
    namespace IO_number{
    	int read(){
    		int x =0; bool f =0; char c =getchar();
    		while(c < '0' || c > '9') ((c == '-') ? f =1 : 0), c =getchar();
    		while(c >= '0' && c <= '9') x =(x<<1)+(x<<3)+(48^c), c =getchar();
    		return (f) ? -x : x;
    	}
    }
    using namespace IO_number;
    
    namespace Dijkstra{
    	namespace Graph{
    		struct edge{
    			int to, w, nxt;
    		}e[MAXN*MAXN*4];
    		int first[MAXN*MAXN], tote;
    		
    		inline void addedge(const int &u, const int &v, const int &w){
    			++tote, e[tote].to =v, e[tote].w =w, e[tote].nxt =first[u], first[u] =tote;
    			++tote, e[tote].to =u, e[tote].w =w, e[tote].nxt =first[v], first[v] =tote;
    		}
    		int rem_first[MAXN*4*3*2], rem_first_id[MAXN*4*3*2], tot_rem;
    		inline void addedge_(const int &u, const int &v, const int &w){
    			rem_first[tot_rem] =first[u], rem_first_id[tot_rem] =u, ++tot_rem;
    			++tote, e[tote].to =v, e[tote].w =w, e[tote].nxt =first[u], first[u] =tote;
    		}
    		void back(){
    			tote -=tot_rem;
    			while(tot_rem){
    				--tot_rem;
    				first[rem_first_id[tot_rem]] =rem_first[tot_rem];
    			}
    		}
    		
    	}
    	using namespace Graph;
    	
    	bool vis[MAXN*MAXN];
    	int dist[MAXN*MAXN];
    	void dijkstra(const int &s){
    		memset(vis, 0, sizeof(vis));
    		memset(dist, 0x3f, sizeof(dist));
    		dist[s] =0;
    		priority_queue<pad, vector<pad>, std::greater<pad> > q;
    		q.push(pad(0, s));
    		while(!q.empty()){
    			pad cur =q.top(); q.pop();
    			if(vis[cur.second])
    				continue;
    			vis[cur.second] =1;
    			for(int l =first[cur.second]; l; l =e[l].nxt)
    				if(!vis[e[l].to] && dist[cur.second]+e[l].w < dist[e[l].to])
    					q.push(pad(dist[e[l].to] =dist[cur.second]+e[l].w, e[l].to));
    		}
    	}
    }
    using namespace Dijkstra;
    
    struct Node{
    	int w, p, t;
    }node[MAXK];
    
    int main(){
    //	freopen("traffic.in", "r", stdin);
    //	freopen("traffic.out", "w", stdout);
    	
    	const int n =read(), m =read(), T =read();
    	int e1[MAXN][MAXN], e2[MAXN][MAXN];
    	// 对偶图 x 行 y 列的格子对应的点编号 ( 且相比原来的网格在外围加了一圈格子 ) //
    	auto get_id =[&](const int &x, const int &y){
    		return x*(m+1)+y;
    	};
    	for(int i =0; i < n-1; ++i)
    		for(int j =0; j < m; ++j){
    			e1[i][j] =read();
    			addedge(get_id(i+1, j), get_id(i+1, j+1), e1[i][j]);
    		}
    	for(int i =0; i < n; ++i)
    		for(int j =0; j < m-1; ++j){
    			e2[i][j] =read();
    			addedge(get_id(i, j+1), get_id(i+1, j+1), e2[i][j]);
    		}
    	int id[4*MAXN]; // 射线 i 顺时针下一个无界面对应的结点编号 //
    	for(int i =1; i <= m; ++i)
    		id[i] =get_id(0, i);
    	for(int i =m+1; i <= m+n; ++i)
    		id[i] =get_id(i-m, m);
    	for(int i =m+n+1; i <= 2*m+n; ++i)
    		id[i] =get_id(n, m-(i-m-n));
    	for(int i =2*m+n+1; i <= 2*m+2*n; ++i)
    		id[i] =get_id(n-(i-2*m-n), 0);
    	
    	for(int _t =0; _t < T; ++_t){
    		const int ki =read();
    		for(int i =0; i < ki; ++i)
    			node[i].w =read(), node[i].p =read(), node[i].t =read();
    		sort(node, node+ki, [&](const Node &A, const Node &B){ return A.p < B.p; });
    		
    		int v[MAXK<<1], tot_v =0, dist_node[MAXK][MAXK];
    		node[ki] =node[0];
    		for(int i =0, new_node =(m+1)*(n+1); i < ki; ++i){
    			for(int j =node[i].p; j != node[i+1].p; j =(j-1+1)%(2*m+2*n)+1)
    				addedge_(new_node, id[j], 0), addedge_(id[j], new_node, 0);
    			if(i+1 < ki)
    				addedge_(new_node, new_node+1, node[i+1].w), addedge_(new_node+1, new_node, node[i+1].w);
    			else
    				addedge_(new_node, (m+1)*(n+1), node[i+1].w), addedge_((m+1)*(n+1), new_node, node[i+1].w);
    			if(node[i].t != node[i+1].t)
    				v[tot_v++] =new_node;
    			++new_node;
    		}
    		if(tot_v == 1){
    			puts("0");
    			continue;
    		}
    		for(int i =0; i < tot_v; ++i){
    			dijkstra(v[i]);
    			for(int j =0; j < tot_v; ++j)
    				dist_node[v[i]-(m+1)*(n+1)][v[j]-(m+1)*(n+1)] =Dijkstra::dist[v[j]];
    		}
    		
    		auto get_dist =[&](const int &A, const int &B){
    			return dist_node[A-(m+1)*(n+1)][B-(m+1)*(n+1)];
    		};
    		ll f[MAXK<<1][MAXK<<1]; memset(f, 0x3f, sizeof(f));
    		for(int i =0; i < tot_v; ++i)
    			v[i+tot_v] =v[i];
    		for(int l =0; l+1 < tot_v*2; ++l)
    			f[l][l+1] =get_dist(v[l], v[l+1]);
    		for(int len =4; len <= tot_v; len +=2)
    			for(int l =0; l+len-1 < tot_v*2; ++l){
    				const int r =l+len-1;
    				f[l][r] =f[l+1][r-1]+get_dist(v[l], v[r]);
    				for(int j =l+1; j <= r-2; j +=2)
    					f[l][r] =min(f[l][r], f[l][j]+f[j+1][r]);
    			}
    		ll ans =0x3f3f3f3f3f3f3f3fll;
    		for(int l =0; l+tot_v-1 < tot_v*2; ++l)
    			ans =min(ans, f[l][l+tot_v-1]);
    		
    		printf("%lld\n", ans);
    		Dijkstra::back();
    	}
    	return 0;
    }
    
    • 1

    信息

    ID
    192
    时间
    3000ms
    内存
    512MiB
    难度
    10
    标签
    递交数
    7457
    已通过
    22
    上传者