Kill The Monster
Problem Description
Xxx正在玩一款遊戲,遊戲地圖上有N個點,這些點之間有M條邊。遊戲系統會在一定時間在某點刷新出一定量的怪,系統刷新出來的怪只會存在1秒,下一秒就會消失。如果那個時間xxx正好在那個點,那麼xxx可以秒殺這個點上的所有怪。另外,xxx還有B次放大招的機會,每次放大招可以秒殺掉當前所在點及與其相鄰點上的所有怪。大招有5秒的冷卻時間,也就是說每次放大後要經過5秒鐘才能再次放大。Xxx想知道T時間內他最多可以殺掉多少隻怪。Xxx可以從任意點開始。系統時間從1開始。
Input
輸入的第一行包含一個整數CT(CT<=50), 表示一共有CT組測試數據。
對於每組測試數據,第一行包含5個整數N、M、T、K、B(1 <= N, T <= 50, 0<=M<= (N-1)*N/2, 0<=K<=10000, 0<=B<=5)。N、M、T意義如上所述,K表示有K個系統刷新。
接下來是M行,每行有3個整數u、v、t(1<=u, v<=N, u!=v, 1<=t<=10)表示從u走到v或者從v走到u需要花費t的時間。數據保證沒有重邊。
然後是K行,每行有3個整數t、p、c(1<=t<=50, 1<=p<=N, 1<=c<=100)表示t時間 在p點刷新出c個怪。
Output
對於每組測試數據,輸出在T時間內xxx最多可以殺掉多少隻怪。
Sample Input
2 5 4 3 9 2 1 2 1 2 3 2 2 4 1 2 5 1 1 1 2 2 1 1 2 2 2 2 3 3 2 4 4 2 5 5 3 3 5 3 4 1 3 5 1 5 4 6 8 2 1 2 1 2 3 2 2 4 1 2 5 1 1 1 1 1 2 1 4 3 1 6 1 1 6 2 1 6 3 1 6 4 1 6 5 1
Sample Output
18 8
Hint
第一組測試數據
第1秒,xxx在點1,普通攻擊
點1走到點2
第2秒,xxx在點2,放大
點2走到點4
第3秒,xxx在點4,普通攻擊
Source
Manager
一道畢竟典型的DP,維數較多的情況下各個維的範圍都不高,很像我高一參加的某界NOIP初賽的題目,根據已有的狀態更新新的狀態即可,設DP[點][時間][使用大招數][大招此時冷卻時間],下面怎麼推我想你應該知道了吧。
代碼:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<string>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<cmath>
#define rep(i,n) for(i=1;i<=n;i++)
#define MM(a,t) memset(a,t,sizeof(a))
#define INF 1e9
typedef long long ll;
#define mod 1000000007
using namespace std;
int val[52][52],map[52][52];
int n,m,t,k,b;
int dp[62][62][12][12];
int bbv[62][62];
int calsum(int node,int ti)
{
int i,j,res=0;
if(bbv[node][ti]!=-1) return bbv[node][ti];
rep(i,n)
if(node!=i && map[node][i]!=-1)
res+=val[i][ti];
return bbv[node][ti]=res;
}
int main()
{
int i,j,T,bs,cd,y;
scanf("%d",&T);
while(T--)
{
MM(val,0); MM(map,-1); MM(bbv,-1);
scanf("%d%d%d%d%d",&n,&m,&t,&k,&b);
rep(i,m)
{
int s,e,v;
scanf("%d%d%d",&s,&e,&v);
map[s][e]=map[e][s]=v;
}
rep(i,n) map[i][i]=1;
rep(i,k)
{
int no,ti,v;
scanf("%d%d%d",&ti,&no,&v);
val[no][ti]+=v;
}
MM(dp,-1);
rep(i,n)
{
dp[i][1][0][0]=val[i][1];
dp[i][1][1][5]=val[i][1]+calsum(i,1);
}
int ans=0;
rep(i,t)
rep(j,n)
for(bs=0;bs<=b;bs++)
for(cd=0;cd<=5;cd++)
if(dp[j][i][bs][cd]!=-1)
{
ans=max(ans,dp[j][i][bs][cd]);
rep(y,n)
if(map[j][y]!=-1 && i+map[j][y]<=t)
{
int lt=map[j][y];
int bv=calsum(y,i+lt);
int lc=cd-map[j][y];
if(lc<0) lc=0;
dp[y][i+lt][bs][lc]=max(dp[y][i+lt][bs][lc],dp[j][i][bs][cd]+val[y][i+lt]);
if(lc==0) dp[y][i+lt][bs+1][5]=max(dp[y][i+lt][bs+1][5],dp[j][i][bs][cd]+val[y][i+lt]+bv);
}
}
printf("%d\n",ans);
}
return 0;
}
今天被鎮海中學出的智商題給虐哭了qaq。。。