Educational Codeforces Round 109 (Rated for Div. 2) D. Armchairs(DP)
作者:互联网
- 题目:Armchairs
- 题意:给出n把椅子,将有不超过n/2的人坐在椅子上(标记为1),空椅子则标记为0,将第i把椅子上的人移动到第j把椅子上所花费的时间为abs(j - i),现要求你将这些标记为1的人(一开始就坐在椅子上的人)转移到其他的空椅子上(这些空椅子必须保证从最初到此人转移到该椅子时都是空的,也就是说被标记为0的椅子),求出需要花费最少的时间。
- 解析:此题若能想出动态规划的集合划分,那就很好写了。
- 集合划分:f[i][j]表示前i个人在前j把椅子完成转移操作所花的最少时间(若不能完成则为无穷大)
2.状态转移:- 若该把椅子之前有人坐过(被标记为1),则该把椅子不能被其他人坐,第i个人则无法坐该把椅子:f[i][j] = f[i][j-1];
- 若该把椅子之前为空,则第i个人可以选择转移到该把椅子上:f[i][j] = f[i-1][j-1] + abs(j - pos[i]);
或者不转移到该把椅子上:f[i][j] = f[i][j-1];
两者取一个min即可.
- 集合划分:f[i][j]表示前i个人在前j把椅子完成转移操作所花的最少时间(若不能完成则为无穷大)
- ps:第一次打cf,因为觉得晚上熬夜太伤身,而且舍友打游戏连麦巨吵,没法想题(我睡觉的时候他们都很安静~这很好)就没在晚上打过,终于蹲到个下午场!!!
- 代码:
#include<iostream>
#include<cstring>
using namespace std;
const int N = 5005;
int f[N][N], a[N], pos[N];
int n, cnt = 0;
int main()
{
memset(f, 0x3f, sizeof f);
cin >> n;
for(int i = 1; i <= n; i++)
{
cin >> a[i];
if(a[i]) pos[++cnt] = i; //记录已经被占座的椅子的位置
}
for(int i = 0; i <= n; i++) f[0][i] = 0; //前0个人在前i把椅子中完成转移花费的时间为0
for(int i = 1; i <= cnt; i++)
{
for(int j = 1; j <= n; j++)
{
f[i][j] = f[i][j-1]; //不坐该把椅子
if(!a[j]) //该把椅子原来无人坐
f[i][j] = min(f[i][j-1], f[i-1][j-1] + abs(j - pos[i]));
}
}
cout << f[cnt][n] << endl;
return 0;
}
标签:Educational,Rated,标记,int,Codeforces,转移,pos,Armchairs,椅子 来源: https://www.cnblogs.com/K2MnO4/p/14806053.html