Atcoder ABC 271 (A - F)

A - 484558

大意:十进制转十六进制 , 不足用0补齐
思路:直接套公式

string s;
int n;
 
int main(){
	cin >> n;
	printf("%02X",n); 
	return 0;
}

B - Maintain Multiple Sequences

 vector<int>ve[N];
 
int n , m ,t ,k;
 
int main(){
	
	cin >> n>> m;
	
	for(int i=1;i<=n;i++){
		cin >> t;
		for(int j=1;j<=t;j++){
			cin >> k;
			ve[i-1].push_back(k);
		}
	}	
	
	
	for(int i=1;i<=m;i++){
		
		int l ,r;
		
		cin >> l >> r;
		
		cout << ve[l-1][r-1] << "\n" ;
		
	}
	return 0;
}

C - Manga

大意:给定 n 个数 , 你可以执行一个操作,把两个数变成一个数 , 求从 1 开始的最多能走到那一个数
思路:给每个数都做上标记 , 然后记录一下总的数个数,排个序 , 然后从1开始贪心的跳标记,找到一个有标记的数,标记后移 , 总数减一, 找到一个数没有标记 , 那么总数减 2 ,知道 一个数你没有标记切总数小于2的时候(标记 - 1)即是答案;

int a[N] ;
unordered_map<int,int>vis;

int n , k;

int main(){

	cin >> n;
	
	for(int i=1;i<=n;i++){
		cin >> a[i];
		vis[a[i]] = 1;
	}
	
	sort(a+1,a+1+n);
	
	int now = 1 , ans = n;
	
	while(ans){
		
		if(vis[now]){
			ans--;
			now++;
		}else{
			ans--;
			if(!ans) break;
			ans--;
			now++;
		}
	}
	cout << now - 1 ;
	return 0;
}

D - Flip and Adjust

大意: n 张卡牌 , 每张卡牌两个面 , 可以选择其中一个面朝上 , 问是否可以使得朝上的卡牌总和为 m ,如果存在方案输出每张卡牌的正反面
思路:搜索肯定不行 , 考虑dp转移状态 , 所以就是 dp + 记录路径

string s;

bool dp[110][10010];
int pre[110][10010];

//表示 第 i个位置  总和为 j 是否合法

int a[101][2];

int n , m;

int main(){


	cin >> n >> m; 
	
	for(int i=1;i<=n;i++){
		cin >> a[i][0] >> a[i][1];
	}
	
	dp[0][0] = 1;
	
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(j - a[i][0] >= 0 && dp[i - 1][j - a[i][0]]){
				 dp[i][j] = 1;
				 pre[i][j] = a[i][0]; 
			}
			if(j - a[i][1] >= 0 && dp[i - 1][j - a[i][1]]){
				 dp[i][j] = 1;
				 pre[i][j] = a[i][1];
			} 
		}
	}
	
	
	string s = "";
	
	
	if(dp[n][m]){
		cout << "Yes\n";
		while(pre[n][m]){
			
			if(pre[n][m] == a[n][0]){
				s = 'H' + s;
			}else{
				s = 'T' + s;
			}
			n = n - 1;
			m = m - pre[n + 1][m];
		}
		
		cout << s;
		
	}else{
		cout << "No\n";
	}






	return 0;
}

E - Subsequence Path

大意:
求1 - n 的最短路 , 且最短路要是给定序列的子序列 ;
思路:
假如要求的最短路真的是序列的子序列 , 那么直接按照序列松弛 , 不会影响 最短路的存在 , 倘若不是 , 那按序列松弛所有路径也不会产生新的最短路 , 那么直接按照序列松弛即可

int n , m , k , t;

int a[N] , b[N] , c[N];

ll dis[N];

int main(){

	cin >> n >> m >> k;
	
	
	for(int i=1;i<=n;i++) dis[i]=infl;
	dis[1]=0;
	
	for(int i=1;i<=m;i++){
		a[i] = read();
		b[i] = read();
		c[i] = read();
	}
	
	for(int i=1;i<=k;i++){
		t = read();
		
		dis[b[t]] = min(dis[b[t]] , dis[a[t]] + c[t]);
	}
	
	if(dis[n] == infl){
		cout << "-1";
	}else{
		cout << dis[n];
	}
	return 0;
}

F - XOR on Grid Path

大意:
给定一个 n × n 的方针,从 1 1 走到 n n 问有多少条路径连续异或和为 0
思路:
直接爆搜肯定会爆 , 考虑用空间换时间 , 双向搜索,把状态记到对角线上

string s;
unordered_map<ll,ll>mp[21];
int n;
int a[21][21];

ll ans = 0;

void dfs1(int x ,int y, ll v){
	
//	cout << x << " " << y << "\n" ;
	
	if(x + y == n + 1){
		mp[x][v]++;
//		cout << v << "\n";
		return ;
	}
	
	if(x < n) dfs1(x + 1 , y , v ^ a[x + 1][y]);
	if(y < n) dfs1(x , y + 1 , v ^ a[x][y + 1]);
	
}


void dfs2(int x , int y , ll v){
	if(x + y == n + 1){
		ans += mp[x][v ^ a[x][y]];
		return ;
	}
	if(x > 1) dfs2(x - 1 , y , v ^ a[x - 1][y]);
	if(y > 1) dfs2(x , y - 1 , v ^ a[x][y - 1]);
}
int main(){
	cin >> n;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			cin >> a[i][j];
		}
	}
	dfs1( 1, 1, a[1][1]);
	dfs2( n, n, a[n][n]);
	cout << ans ;
	return 0;
}

你可能感兴趣的:(算法,动态规划,c++)