D. Minimax Problem(二分)

25 篇文章 1 订阅

题目链接:D. Minimax Problem

time limit per test:5 seconds
memory limit per test:512 megabytes
inputstandard input
outputstandard output

You are given n arrays a1, a2, …, an; each array consists of exactly m integers. We denote the y-th element of the x-th array as ax,y.

You have to choose two arrays ai and aj(1≤i,j≤n, it is possible that i=j). After that, you will obtain a new array b consisting of m integers, such that for every k∈[1,m] bk=max(ai,k,aj,k).

Your goal is to choose i and j so that the value of ∑ k = 1 m \sum_{k=1}^m k=1mbk is maximum possible.

Input
The first line contains two integers n and m (1≤n≤3⋅105, 1≤m≤8) — the number of arrays and the number of elements in each array, respectively.

Then n lines follow, the x-th line contains the array ax represented by m integers ax,1, ax,2, …, ax,m (0≤ax,y≤109).

Output
Print two integers i and j (1≤i,j≤n, it is possible that i=j) — the indices of the two arrays you have to choose so that the value of ∑ k = 1 m \sum_{k=1}^m k=1mbk is maximum possible. If there are multiple answers, print any of them.

Example
input

6 5
5 0 3 1 2
1 8 9 1 3
1 2 3 4 5
9 1 0 3 7
2 3 0 6 3
6 4 1 7 0

output

1 5

题目大意

给你两个数,n和m,表示n个数组每个数组有m个元素,然后让你输出任意两个数组合并后数组中的最小值最大是几,合并的规则是两个数组的同一个位置取最大值,比如:1 2 3 4 5 和 5 4 3 2 1这两个数列合并后的值为 5 4 3 4 5;最小值时3;

解题思路

既然是求最小值最大,那么很容易想到二分,但是我们该如何check呢?当行很大,列很小的时候很容易想到状压,但是如何表示状态呢?,既然是两个数列合并后的最小值都要大于二分的 mid,所以用二进制来表示每个数列满足要求的状态,比如说一共4个数 现在需要合并后的值大于等于3 两个数列是 1 3 4 1 那么这个数列满足大于等于3的值可以用6表示(第2位和第3位大于等于三,也就是二进制的第二位和第三位唯一,结果是6)另一个是4 1 3 4 状态表示为11,然后6|11等于列数4所以可以,如果不等那就不成立,现在我们check和二分都有了,就可以码代码了。

代码

#include<bits/stdc++.h>
using namespace std;
int a[500000][10];//存图 
int ans[1000];//判断这个状态是否成立 
int ans_pos[1000];//表示这个成立这个状态是第几行 
int n,m;
int ans1,ans2;//记录成立的两个状态 
bool check(int x)
{
	int t;
	memset(ans,0,sizeof ans);//每次初始化状态数组 
	for(int i=1;i<=n;i++)
	{
		t=0;//记录状态 
		for(int j=0;j<m;j++)
		{							//这里的 位运算 | 简化了相互的加法,不懂得自己模拟一遍 
			if(a[i][j]>=x) t|=(1<<j);// j的第几个元素满足情况,第几位为 1 
		}
		ans[t]=1;//这个状态存在,就唯一; 
		ans_pos[t]=i;//记录这个状态是第几行; 
	}
	int k=1<<m;//一共 m 列如果都是 1 那么 二进制就是 m 个1 
	for(int i=0;i<k;i++)
	{
		if(!ans[i]) continue;//如果这个状态为0,说明不存在 
		for(int j=0;j<k;j++)
		{
			if(!ans[j]) continue;
			if((i|j)==k-1)//如果 两个位置 或 后等于k,那么说明情况合法 
			{
				ans1=ans_pos[i];//ans1 ans2 满足此状态的两行行数 
				ans2=ans_pos[j];// 
				return 1;
			}
		}
	}
	return 0;
}
int main()
{
	ios::sync_with_stdio(0);
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		for(int j=0;j<m;j++)
		cin>>a[i][j];
	}
	int l=0,r=0x3f3f3f3f;
	int mid;
	while(l<=r)//二分模板写法 
	{
		mid=(l+r)/2;
		if(check(mid)) l=mid+1;
		else r=mid-1;
	}
	cout<<ans1<<" "<<ans2<<'\n';
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Minimax is a popular algorithm used in game theory and artificial intelligence to determine the optimal move for a player in a game with perfect information. It is often used in games such as chess, tic-tac-toe, and Connect Four. In C#, you can implement the Minimax algorithm by representing the game state and creating a recursive function to search through all possible moves and evaluate their outcomes. Here's a simplified example of Minimax in C#: ```csharp public int MiniMax(int[] board, int depth, bool isMaximizingPlayer) { // Base case: check if the game is over or the maximum depth is reached if (IsGameOver(board) || depth == 0) { return Evaluate(board); } if (isMaximizingPlayer) { int bestScore = int.MinValue; foreach (int move in GetPossibleMoves(board)) { int[] newBoard = MakeMove(board, move); int score = MiniMax(newBoard, depth - 1, false); bestScore = Math.Max(bestScore, score); } return bestScore; } else { int bestScore = int.MaxValue; foreach (int move in GetPossibleMoves(board)) { int[] newBoard = MakeMove(board, move); int score = MiniMax(newBoard, depth - 1, true); bestScore = Math.Min(bestScore, score); } return bestScore; } } // Example usage: int[] board = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; int bestMove = -1; int bestScore = int.MinValue; foreach (int move in GetPossibleMoves(board)) { int[] newBoard = MakeMove(board, move); int score = MiniMax(newBoard, depth, false); if (score > bestScore) { bestScore = score; bestMove = move; } } Console.WriteLine("Best move: " + bestMove); ``` This is a simplified example, and you would need to implement the `IsGameOver()`, `Evaluate()`, `GetPossibleMoves()`, and `MakeMove()` functions according to the rules of your specific game. The `depth` parameter controls the depth of the search tree, determining how far ahead the algorithm looks. Adjusting this parameter can affect the algorithm's performance and the quality of the decisions it makes.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值