P9791 [NERC2018] Alice the Fan 题解
思路
发现
设
转移比较麻烦,按照题目描述一步步来。
首先考虑
需要注意,转移的那个状态要满足
然后考虑加时赛。
还是枚举哪个队伍取得胜利,同时枚举比赛结束时双方得了多少分。
接着就是前
最后记录当前状态是从哪里转移过来的,倒序输出即可。
AC 代码
#include<bits/stdc++.h>
using namespace std;
int t;
int n,m;
int dp[220][220][10][10];
struct node{
int aa,bb,cc,dd;
};
node ans[220][220][10][10];
bool operator==(node x,node y){
return x.aa == y.aa && x.bb == y.bb && x.cc == y.cc && x.dd == y.dd;
}
bool operator!=(node x,node y){
return !(x == y);
}
void go_work(){
dp[0][0][0][0] = 1;
for(int i = 0; i <= 200; i++){
for(int j = 0; j <= 200; j++){
for(int x = 0; x <= 3; x++){
for(int y = 0; y <= 3; y++){
if(x+y == 5){
if(i >= 15 && x >= 1 && y != 3){
for(int q = 0; q <= min(13,j); q++){
if(dp[i-15][j-q][x-1][y]){
dp[i][j][x][y] = 1;
ans[i][j][x][y] = {i-15,j-q,x-1,y};
}
}
}
if(j >= 15 && y >= 1 && x != 3){
for(int q = 0; q <= min(13,i); q++){
if(dp[i-q][j-15][x][y-1]){
dp[i][j][x][y] = 1;
ans[i][j][x][y] = {i-q,j-15,x,y-1};
}
}
}
for(int q = 16; q <= min(i,j)+2; q++){
if(i >= q && j >= q-2 && x >= 1 && y != 3){
if(dp[i-q][j-q+2][x-1][y]){
dp[i][j][x][y] = 1;
ans[i][j][x][y] = {i-q,j-q+2,x-1,y};
}
}
if(i >= q-2 && j >= q && y >= 1 && x != 3){
if(dp[i-q+2][j-q][x][y-1]){
dp[i][j][x][y] = 1;
ans[i][j][x][y] = {i-q+2,j-q,x,y-1};
}
}
}
}else{
if(i >= 25 && x >= 1 && y != 3){
for(int q = 0; q <= min(23,j); q++){
if(dp[i-25][j-q][x-1][y]){
dp[i][j][x][y] = 1;
ans[i][j][x][y] = {i-25,j-q,x-1,y};
}
}
}
if(j >= 25 && y >= 1 && x != 3){
for(int q = 0; q <= min(23,i); q++){
if(dp[i-q][j-25][x][y-1]){
dp[i][j][x][y] = 1;
ans[i][j][x][y] = {i-q,j-25,x,y-1};
}
}
}
for(int q = 26; q <= min(i,j)+2; q++){
if(i >= q && j >= q-2 && x >= 1 && y != 3){
if(dp[i-q][j-q+2][x-1][y]){
dp[i][j][x][y] = 1;
ans[i][j][x][y] = {i-q,j-q+2,x-1,y};
}
}
if(i >= q-2 && j >= q && y >= 1 && x != 3){
if(dp[i-q+2][j-q][x][y-1]){
dp[i][j][x][y] = 1;
ans[i][j][x][y] = {i-q+2,j-q,x,y-1};
}//l
}//u
}//f
}//i
}//t
}//u
}//a
}//e
}//b
stack<pair<int,int>> prt;
int main(){
go_work();
scanf("%d",&t);
while(t--){
static node tp,now;
scanf("%d%d",&n,&m);
while(prt.size()){
prt.pop();
}
if(dp[n][m][3][0]){
puts("3:0");
now = (node){n,m,3,0};
tp = ans[n][m][3][0];
while(now != (node){0,0,0,0}){
prt.push({now.aa-tp.aa,now.bb-tp.bb});
now = tp;
tp = ans[tp.aa][tp.bb][tp.cc][tp.dd];
}
while(prt.size()){
printf("%d:%d ",prt.top().first,prt.top().second);
prt.pop();
}
puts("");
}else if(dp[n][m][3][1]){
puts("3:1");
now = (node){n,m,3,1};
tp = ans[n][m][3][1];
while(now != (node){0,0,0,0}){
prt.push({now.aa-tp.aa,now.bb-tp.bb});
now = tp;
tp = ans[tp.aa][tp.bb][tp.cc][tp.dd];
}
while(prt.size()){
printf("%d:%d ",prt.top().first,prt.top().second);
prt.pop();
}
puts("");
}else if(dp[n][m][3][2]){
puts("3:2");
now = (node){n,m,3,2};
tp = ans[n][m][3][2];
while(now != (node){0,0,0,0}){
prt.push({now.aa-tp.aa,now.bb-tp.bb});
now = tp;
tp = ans[tp.aa][tp.bb][tp.cc][tp.dd];
}
while(prt.size()){
printf("%d:%d ",prt.top().first,prt.top().second);
prt.pop();
}
puts("");
}else if(dp[n][m][2][3]){
puts("2:3");
now = (node){n,m,2,3};
tp = ans[n][m][2][3];
while(now != (node){0,0,0,0}){
prt.push({now.aa-tp.aa,now.bb-tp.bb});
now = tp;
tp = ans[tp.aa][tp.bb][tp.cc][tp.dd];
}
while(prt.size()){
printf("%d:%d ",prt.top().first,prt.top().second);
prt.pop();
}
puts("");
}else if(dp[n][m][1][3]){
puts("1:3");
now = (node){n,m,1,3};
tp = ans[n][m][1][3];
while(now != (node){0,0,0,0}){
prt.push({now.aa-tp.aa,now.bb-tp.bb});
now = tp;
tp = ans[tp.aa][tp.bb][tp.cc][tp.dd];
}
while(prt.size()){
printf("%d:%d ",prt.top().first,prt.top().second);
prt.pop();
}
puts("");
}else if(dp[n][m][0][3]){
puts("0:3");
now = (node){n,m,0,3};
tp = ans[n][m][0][3];
while(now != (node){0,0,0,0}){
prt.push({now.aa-tp.aa,now.bb-tp.bb});
now = tp;
tp = ans[tp.aa][tp.bb][tp.cc][tp.dd];
}
while(prt.size()){
printf("%d:%d ",prt.top().first,prt.top().second);
prt.pop();
}
puts("");
}else{
puts("Impossible");
}
}
return 0;
}
说这是 DP 谁信啊,分明就是 TMD 大模拟。