Castle Protecting
数据描述:
darkkingdom侵占了wisekingdom的st.acerburg,为了消灭敌人夺回城堡,st.acerburg的臣民决定向城堡投一种特
殊的炸弹。这种炸弹的毁灭范围是一个矩形(即可以炸一个格子,或连续两个格子,或连续四个格子……可以控制范围,但
必须是矩形)。st.acerburg的城堡比较特殊,他只有两层,但是很长。臣民们知道城堡上有N个敌人,并且知道他们在啊a
[i][0]层楼的a[i][1]间房。现在他们手中有K枚炸弹,他们将消灭在城堡内的敌人,但是并不愿意破坏自己城堡的房子。他
们想知道最少要破坏多少间房子才能消灭敌人。
输入格式:
第一行:三个整数N,K,B。分别为敌人的数目,炸弹的数目和城堡的长度。
n,k<=1000;B<=15000000;
接下来N行每行两个数,a[i][0],a[i][1]
输出格式:
仅一行,最少需要破坏的房屋数目
样例输入:
8 2 9
1 2
1 6
1 7
1 8
1 9
2 2
2 3
2 4
样例输出:
10
数据:
30% N,K<=20
60% N,K<=200
100% N,K<=1000
这道题不难看出是dp,稍有后效性。
开始看题时以为只能两层楼分别炸,结果他是可以一起炸的。
先按房子位置排个序,令状态f[i][j][k](0<=k<=2)表示用了j个炸弹将第i个敌人以k种方式kill掉的最小费用。
type0:仅将第i个敌人所在的房间炸掉;
type1:将第i个敌人和他同一列的另一个房间用同一个炸弹炸掉;
type2:将第i个敌人和他同一列的同一个房间用不同炸弹炸掉。
f[i][j][0]=min{f[i-1][j-1][k]+1, f[i-1][j][0]+(len[i]-len[i-1])(在同一层楼) , f[i-1][j][2]+(len[i]-len[i-1])};
f[i][j][1]=min{f[i-1][j-1][k]+2 , f[i-1][j][1]+2*(len[i]-len[i-1])};
f[i][j][2]=min{f[i-1][j-2][k]+2 , f[i-1][j-1][0]+(len[i]-len[i-1])+1 , f[i-1][j][2]+2*(len[i]-len[i-1])};
<textarea class="c++" name="code" readonly="readonly">
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
const int maxn=1005;
int N,M,B;
int f[maxn][maxn][3];
int X[maxn],Y[maxn];
inline void upmin(int &x,int t){if(t<x)x=t;}
int main()
{
freopen("castle.in","r",stdin);
freopen("castle.out","w",stdout);
scanf("%d%d%d",&N,&M,&B);
for(int i=1;i<=N;++i)scanf("%d%d",&Y[i],&X[i]);
for(int i=1;i<N;++i)
for(int j=i+1;j<=N;++j)
if(X[j]<X[i])swap(X[i],X[j]),swap(Y[i],Y[j]);
const int inf=1000000000;
f[1][0][0]=f[1][0][1]=f[1][0][2]=inf;
f[1][1][0]=1,f[1][1][1]=2,f[1][2][2]=2,f[1][1][2]=inf;
for(int i=2;i<=N;++i)
for(int j=1;j<=i&&j<=M;++j)
{
f[i][j][0]=f[i][j][1]=f[i][j][2]=inf;
if(j>1)for(int k=0;k<3;++k)upmin(f[i][j][0],f[i-1][j-1][k]+1);
if(i>j&&Y[i]==Y[i-1])upmin(f[i][j][0],f[i-1][j][0]+X[i]-X[i-1]);
if(i>j)upmin(f[i][j][0],f[i-1][j][2]+X[i]-X[i-1]);
if(j>1)for(int k=0;k<3;++k)upmin(f[i][j][1],f[i-1][j-1][k]+2);
if(i>j)upmin(f[i][j][1],f[i-1][j][1]+2*(X[i]-X[i-1]));
if(i>=j-1&&j>2)for(int k=0;k<3;++k)upmin(f[i][j][2],f[i-1][j-2][k]+2);
if(j>1)upmin(f[i][j][2],f[i-1][j-1][0]+(X[i]-X[i-1]+1));
if(i>j)upmin(f[i][j][2],f[i-1][j][2]+2*(X[i]-X[i-1]));
}
int Ans=inf;
for(int i=min(M,N);i;--i)
for(int k=0;k<3;++k)
upmin(Ans,f[N][i][k]);
printf("%d\n",Ans);
return 0;
}
</textarea>