题目大意:
a和b在玩游戏,a每次都可以选择一行,b每次都可以选择一列。规定选完的行或者列不能再选。每次a选完第i一行后,b都可以选择第j列,然后a会得到对应(i,j)的分数。a想分数尽可能高,b想让a的分数尽可能低。每个人都play optimally,问我们a最后最高能拿多少分。
解题思路:
这里看起来像博弈论问题,我们首先按照暴力的思维,那复杂度大概是:8!* 8!,妥妥tle。这个没有给我们任何启示。接着我们可以尝试贪心,考虑以下棋盘:
1 -2 -3
-3 4 -5
-2 1 3
转载:https://www.redgreencode.com/when-not-to-simulate-a-game-uva-11553/
比如a不想让b选择2行3列的-5,他有什么方法呢?那他可不可以首先选第一行,然后诱惑b选择第三列呢?但是b也是理性人,考虑到后面有-5,他可能就会选择第二列。所以无论a怎么走,我们发现结局依然是不变的!所以这就把问题转化为退化版八皇后,复杂度在8!,选择分数最低的就可以了。
另外本题也可以按照minmax博弈来做,但是需要用状压DP,我们用16位的bitset来记录a和b的行列的轨迹。每次轮到a他只走分数最高的行,每次轮到b他只走分数最低的列,a返回走不同行时得分的最高分,b返回走不同列时得分的最低分。边界条件就是走完返回0.
废话:
看到这题,其实给了我们思路启发就是,有时候题目比较难的时候,可以通过构造更多的样例然后从暴力和贪心不断去尝试,看有没有一些思路的启发。
#include <bits/stdc++.h>
using namespace std;
const int INF=1e9;
vector<vector<int>> gra;
int ans;
int bit;
int val;
int n;
void dfs(int level){
if(level==n){
ans=min(ans,val);
return ;
}
for(int i=0;i<n;i++){
if(bit&(1<<i))continue;
bit|=1<<i;
val+=gra[level][i];
dfs(level+1);
bit&=~(1<<i);
val-=gra[level][i];
}
}
int main(){
int cas;cin>>cas;
while(cas--){
cin>>n;
gra.assign(n,vector<int>(n));
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
cin>>gra[i][j];
ans=INF;
val=0;
dfs(0);
cout<<ans<<endl;
}
return 0;
}