D的大意就是能否找到一个按题目要求的模拟的东西
首先一个数想要到达终点 他经过的点都是要和他一个终点的 并且终点的终点是他自己
那么就可以先把所有终点的终点是自己的 且 其他点的终点是他的终点的 dfs出来
如果是死循环的话 那么就先两两互相连 比如 左边的点到右 然后右边的点到左 这个时候在dfs找一下有没有和他们一样需要死循环的就行了
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 3100;
int a[N][N],flag[N][N];char out[N][N];
int b[N][N];
int xx[4] = {0,1,0,-1};
int yy[4] = {1,0,-1,0};
void dfs(int x,int y){
flag[x][y] = 1;
for(int i = 0; i < 4; i++){
int dx = x + xx[i],dy = y + yy[i];
if(flag[dx][dy]) continue;
if(a[x][y] == a[dx][dy] && b[x][y] == b[dx][dy]){
if(xx[i] == 1){
out[dx][dy] = 'U';
}else if(xx[i] == -1) out[dx][dy] = 'D';
else if(yy[i] == 1) out[dx][dy] = 'L';
else out[dx][dy] = 'R';
dfs(dx,dy);
}
}
}
int main(){
int n;
cin >> n;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
scanf("%d",&a[i][j]);
scanf("%d",&b[i][j]);
}
}
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
out[i][j] = 'A';
}
}
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
if(i == a[i][j] && j == b[i][j]){
out[i][j] = 'X';
dfs(i,j);
}
}
}
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
if(flag[i][j]) continue;
if(a[i][j] == -1 && a[i][j + 1] == -1){
out[i][j] = 'R',out[i][j + 1] = 'L';
flag[i][j + 1] = 1;
dfs(i,j);
dfs(i,j + 1);
}else if(a[i][j] == -1 && a[i + 1][j] == -1){
out[i][j] = 'D',out[i + 1][j] = 'U';
flag[i + 1][j] = 1;
dfs(i,j);
dfs(i + 1,j);
}
}
}
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
if(out[i][j] == 'A'){
cout << "INVALID" << endl;
return 0;
}
}
}
cout << "VALID" << endl;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
cout << out[i][j];
}
cout << endl;
}
return 0;
}
E一看题目就能知道是个状压dp但是如何去处理K个人的那一部分呢 我们可以sort一下然后将大的观众放在前面 如果这个人没有被选到队伍里面 并且观众不够的话 那么他必然是观众 因为后面的观众值都没他大 所以只要一个状压dp就完事了
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1e5 + 10;
typedef long long ll;
struct node{
ll gz,dy[10];
bool operator < (const node &p)const{
return gz > p.gz;
}
}a[N];
ll dp[N][1 << 8],sum = 0;
int main(){
int n,p,k;
cin >> n >> p >> k;
for(int i = 1; i <= n; i++){
scanf("%lld",&a[i].gz);
}
for(int i = 1; i <= n; i++){
for(int j = 1; j <= p; j++){
scanf("%lld",&a[i].dy[j]);
}
}
sort(a + 1,a + n + 1);
memset(dp,-0x3f,sizeof dp);
dp[0][0] = 0;
for(int i = 1; i <= n; i++){
for(int j = 0; j < (1 << p); j++){
dp[i][j] = dp[i - 1][j];
}
for(int j = 0; j < (1 << p); j++){
int h = 0;
for(int d = 0; d < p; d++){
if((j & (1 << d)) == 0){
dp[i][j ^ (1 << d)] = max(dp[i - 1][j] + (a[i].dy[d + 1]),dp[i][j ^ (1 << d)]);
}else ++h;
}
if(i - h <= k){
dp[i][j] = max(dp[i][j],dp[i - 1][j] + a[i].gz);
}
}
}
cout << dp[n][(1 << p) - 1] <<endl;
return 0;
}