标签:include init cost 失败 hid 过程 存在 display 特殊
#include<bits/stdc++.h> using namespace std; const int maxn=((1<<17)+1014); int N,K; int a[maxn]; int dp[18][maxn][2][2]; //dp[i][j][x1][y1]表示从j开始,连续的2^(i)个人比赛, //胜利组胜出的人是不是(1/0)你喜欢的队 //失败组胜出的人是不是(1/0)你喜欢的队 // dp数组的值表示你喜欢的队伍目前参与了多少场比赛 void init () { //初始化,把所有的DP值全部初始化为负无穷 for (int i=0;i<18;i++) { for (int j=0;j<maxn;j++) { for (int k=0;k<2;k++) { for (int z=0;z<2;z++) { dp[i][j][k][z]=-1e9; } } } } } int main () { init (); scanf("%d%d",&N,&K); for (int i=0;i<K;i++) { int x; scanf("%d",&x); a[x-1]=1;//统一把编号往前挪一位 } for (int i=1;i<=N;i++) { //i从1开始加到N,不断倍增,就是一个从第一轮比赛推到最后一轮决赛的过程 for (int j=0;j<(1<<N);j+=(1<<i)) { //2^i支队伍为一组,遍历每一组队伍 if (i==1) { //如果只有两支队伍,特殊处理,此时只有胜者组 for (int x1=0;x1<2;x1++) { for (int y1=0;y1<2;y1++) { if (x1+y1==a[j]+a[j+1]) dp[i][j][x1][y1]=((a[j]+a[j+1])>0?1:0); //遍历有比赛情况 //如果两只队伍都是喜欢的队伍,那就一定都会进入下一轮(一个胜者组,一个败者组 //如果两只队伍有一支是喜欢的队伍,那么最多只可能有一支喜欢的队伍进入下一轮(胜者组或败者组) //如果两只队伍都不是喜欢的队伍,那么不会有队伍进入下一轮。 //dp最后的值是,如果存在喜欢的队伍,那么不管有一支或两支,它们最多也只能参加一场比赛,所以如式子所示 } } } else { //有多支队伍,分为胜者组和败者组 for (int x1=0;x1<2;x1++) { for (int y1=0;y1<2;y1++) { for (int x2=0;x2<2;x2++) { for (int y2=0;y2<2;y2++) { //遍历上一轮两组队伍的所有的比赛情况 //x1,y1代表胜利组,x2,y2代表失败组 int cost=dp[i-1][j][x1][y1]+dp[i-1][j+(1<<(i-1))][x2][y2]; //定义当前你喜欢的队伍参与的比赛数量cost是上一轮的两个组分别的dp值之和 if (x1||x2) cost++; //如果胜者组至少有一个你喜欢的队伍留下来了,那么你喜欢的队伍会参加当前的比赛,cost值加一 if (y1||y2) cost++; //如果败者组至少有一个你喜欢的队伍留下了了,那么你喜欢的队伍会参加当前的比赛,cost值加一 //接下来枚举八种比赛状态 dp[i][j][x1][x2]=max(dp[i][j][x1][x2],cost+((x2+y1)>0?1:0)); dp[i][j][x1][y1]=max(dp[i][j][x1][y1],cost+((x2+y1)>0?1:0)); //上一轮比赛胜出的是x1,y1,那么y1会和x2再比一场,y2直接淘汰 dp[i][j][x1][x2]=max(dp[i][j][x1][x2],cost+((x2+y2)>0?1:0)); dp[i][j][x1][y2]=max(dp[i][j][x1][y2],cost+((x2+y2)>0?1:0)); //上一轮比赛胜出的是x1,y2,那么y2会和x2再比一场,y1直接淘汰 dp[i][j][x2][x1]=max(dp[i][j][x2][x1],cost+((x1+y2)>0?1:0)); dp[i][j][x2][y2]=max(dp[i][j][x2][y2],cost+((x1+y2)>0?1:0)); //上一轮比赛胜出的是x2,y2,那么x1会和y2再比一场,y1直接淘汰 dp[i][j][x2][x1]=max(dp[i][j][x2][x1],cost+((x1+y1)>0?1:0)); dp[i][j][x2][y1]=max(dp[i][j][x2][y1],cost+((x1+y1)>0?1:0)); } //上一轮比赛胜出的是x2,y1,那么x1会和y1再比一场,y2直接淘汰 } } } } } } int ans=0; for (int i=0;i<2;i++) { for (int j=0;j<2;j++) { int cost=dp[N][0][i][j]; //cost表示2^N支队伍遍历完,比赛结束的四种比赛状态 if (i+j) cost++;//如果存在喜欢的队伍,就把决赛也算进去 ans=max(ans,cost); } } printf ("%d\n",ans); return 0; }
标签:include init cost 失败 hid 过程 存在 display 特殊
原文地址:https://www.cnblogs.com/zhanglichen/p/12384847.html