题目:http://www.codeforces.com/contest/254
D:任意找一个R点bfs找到能炸死它的位置,枚举所有位置,对于位置A,再找一个A炸不到的R点,bfs找到能炸死它的所有位置,再枚举位置,对于枚举的位置B,判断一下A,B能不能炸死所有的老鼠。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<math.h>
#include<string>
#include<map>
#include<set>
#include<iostream>
using namespace std;
typedef long long ll;
const int inf = 1 << 29;
#define N 1010
char a[N][N];
struct node{
int x,y;
int step;
};
int dd[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
int n,m;
int vis[20][20];
vector<pair<int,int> > e[2];
set<pair<int,int> > S,ans;
void bfs(int si,int sj,int d,int k)
{
node t,tt;
queue<node> qu;
t.x=si,t.y=sj;t.step=0;
memset(vis,0,sizeof(vis));
vis[d][d]=1;
qu.push(t);
while(!qu.empty()){
t=qu.front();qu.pop();
if (k==1) {
if (a[t.x][t.y] != 'X') {
e[0].push_back(make_pair(t.x, t.y));
}
}else if(k==0){
if (a[t.x][t.y] == 'R')
S.insert(make_pair(t.x, t.y));
}else if(k==2){
if (a[t.x][t.y] != 'X')
e[1].push_back(make_pair(t.x, t.y));
}
else if (k == 3) {
if (a[t.x][t.y] == 'R')
ans.insert(make_pair(t.x, t.y));
}
if(t.step>=d) continue;
tt.step=t.step+1;
for(int i=0;i<4;i++){
tt.x=t.x+dd[i][0];
tt.y=t.y+dd[i][1];
if(tt.x<0||tt.x>=n||tt.y<0||tt.y>m) continue;
if(a[tt.x][tt.y]=='X') continue;
if(vis[tt.x-si+d][tt.y-sj+d]) continue;
vis[tt.x-si+d][tt.y-sj+d]=1;
qu.push(tt);
}
}
}
vector<pair<int,int> > R;
int main() {
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);
int d;
scanf("%d%d%d",&n,&m,&d);
for(int i=0;i<n;i++)
scanf("%s",a[i]);
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++) {
if (a[i][j] == 'R') {
R.push_back(make_pair(i,j));
}
}
bfs(R[0].first,R[0].second,d,1);
for(int i=0;i<(int)e[0].size();i++){
S.clear();
bfs(e[0][i].first, e[0][i].second, d,0);
e[1].clear();
if (S.size() == R.size()) {
for (int j = 0; j < n; j++)
for (int k = 0; k < m; k++) {
if ((j != e[0][i].first || k != e[0][i].second)
&& a[j][k] != 'X') {
printf("%d %d %d %d\n", e[0][i].first+1, e[0][i].second+1,j+1, k+1);
return 0;
}
}
}
for(int j=1;j<(int)R.size();j++){
if(S.find(R[j])==S.end()){
bfs(R[j].first,R[j].second,d,2);
break;
}
}
for(int j=0;j<(int)e[1].size();j++){
ans.clear();
for(set<pair<int,int> >::iterator it=S.begin();it!=S.end();it++)
ans.insert(*it);
bfs(e[1][j].first, e[1][j].second, d,3);
if(ans.size()==R.size()){
printf("%d %d %d %d\n",e[0][i].first+1,e[0][i].second+1,e[1][j].first+1, e[1][j].second+1);
return 0;
}
}
}
printf("-1\n");
}
E:dp题,dp[i][j]表示i天过后还剩j数量的食物时的最大值,对于第i天枚举朋友数进行转移,记录路径输出
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<math.h>
#include<string>
#include<map>
#include<set>
#include<iostream>
using namespace std;
typedef long long ll;
const int inf = 1 << 29;
int a[410];
vector<pair<int,int> > e[410];
int pre[410][410];
int op[410][410];
int dp[410][410];
void output(int i,int n)
{
if(!i) return;
output(i-1,pre[i][n]);
int k=op[i][n];
printf("%d",k);
for(int j=0;j<k;j++){
printf(" %d",e[i][j].second);
}
puts("");
}
int cost[410][410];
int main() {
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);
int n,v,m,l,r,f;
scanf("%d%d",&n,&v);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
scanf("%d",&m);
for(int i=0;i<m;i++){
scanf("%d%d%d",&l,&r,&f);
for(int j=l;j<=r;j++){
e[j].push_back(make_pair(f,i+1));
}
}
for(int i=1;i<=n;i++){
sort(e[i].begin(),e[i].end());
for(int j=0;j<(int)e[i].size();j++){
cost[i][j+1]=cost[i][j]+e[i][j].first;
}
}
memset(dp,-1,sizeof(dp));
dp[0][0]=0;
for(int i=0;i<n;i++){
for(int j=0;j<=a[i];j++){
if(dp[i][j]==-1) continue;
int t=j+a[i+1];
for(int k=0;k<=(int)e[i+1].size();k++){
if(cost[i+1][k]+v>t) break;
int tt=t-cost[i+1][k]-v;
tt=min(tt,a[i+1]);
if(dp[i+1][tt]<k+dp[i][j]){
dp[i+1][tt]=k+dp[i][j];
pre[i+1][tt]=j;
op[i+1][tt]=k;
}
}
}
}
int ans=-1,pos;
for(int i=0;i<=a[n];i++){
if(ans<dp[n][i]){
ans=dp[n][i];
pos=i;
}
}
printf("%d\n",ans);
output(n,pos);
}