这个题卡时间卡的好变态哇,改了很多次还总是超时,后来找到了罪魁祸首:用来分硬币的函数separate,原本是这样的形式
void separate(int i,int j){
if(ci[i][j].ciuse==-1)return;
if(j-1>=1&&ci[i][j-1].ciuse!=-1){//分给下边的点
for(int k=1;k<=n;k++){
ci[i][j].coint[k]-=ci[i][j].coins[k]/1000;
ci[i][j-1].coint[k]+=ci[i][j].coins[k]/1000;
}
}
if(j+1<=10&&ci[i][j+1].ciuse!=-1){//分给上边的点
for(int k=1;k<=n;k++){
ci[i][j].coint[k]-=ci[i][j].coins[k]/1000;
ci[i][j+1].coint[k]+=ci[i][j].coins[k]/1000;
}
}
if(i+1<=10&&ci[i+1][j].ciuse!=-1){//分给右边的点
for(int k=1;k<=n;k++){
ci[i][j].coint[k]-=ci[i][j].coins[k]/1000;
ci[i+1][j].coint[k]+=ci[i][j].coins[k]/1000;
}
}
if(i-1>=1&&ci[i-1][j].ciuse!=-1){//分给左边的点
for(int k=1;k<=n;k++){
ci[i][j].coint[k]-=ci[i][j].coins[k]/1000;
ci[i-1][j].coint[k]+=ci[i][j].coins[k]/1000;
}
}
}
由于这个函数频率最高,且上面写法涉及到了很多重复计算。推测它是导致超时的主要原因(采用scanf printf的IO方式、优化check效果都不明显),将该函数的重复计算部分进行一点优化就可以了。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<stdlib.h>
#include<stdio.h>
using namespace std;
int n;
struct city
{
int ciuse;
int coindex;
int coins[21];
int coint[21];
city(){
ciuse=coindex=-1;
for(int i=1;i<=20;i++)
coins[i]=coint[i]=0;
}
clear(){
ciuse=coindex=-1;
for(int i=1;i<=20;i++)
coins[i]=coint[i]=0;
}
fun(int coindext){
ciuse=1;
coindex=coindext;
coins[coindex]=1000000;
}
int check(){
for(int i=1;i<=n;i++)
{
coins[i]+=coint[i];//更新coins
coint[i]=0;//清零coint
}
for(int i=1;i<=n;i++){
if(!coins[i]){
return 0;
}
}
return 1;
}
}ci[11][11];
struct country
{
string name;
int x1,y1,x2,y2;
int coindex;
int endtime;
country(){
name="";
x1=y1=x2=y2=coindex=endtime=0x3f3f3f3f;
}
clear(){
name="";
x1=y1=x2=y2=coindex=endtime=0x3f3f3f3f;
}
fun(int coindext,string namet,int x1t,int y1t,int x2t,int y2t){
coindex=coindext;
name=namet;
x1=x1t;
y1=y1t;
x2=x2t;
y2=y2t;
endtime=0x3f3f3f3f;
for(int i=x1;i<=x2;i++){
for(int j=y1;j<=y2;j++){
ci[i][j].fun(coindex);
}
}
}
int check(int d){//改变endtime
int flag=1;
for(int i=x1;i<=x2;i++){
for(int j=y1;j<=y2;j++){
if(ci[i][j].check()==0){
flag=0;
}
}
}
if(flag==0)return 0;
endtime=min(d,endtime);
return 1;
}
}co[21];
bool cmp(country c1,country c2){
if(c1.endtime!=c2.endtime)return c1.endtime<c2.endtime;
else return strcmp(c1.name.c_str(),c2.name.c_str())<0;
}
void clear(){
for(int i=1;i<=n;i++){
co[i].clear();
}
for(int i=1;i<=10;i++){
for(int j=1;j<=10;j++)
ci[i][j].clear();
}
}
void separate(int i,int j){
if(ci[i][j].ciuse==-1)return;
int cointmp[21];
for(int m=1;m<=n;m++)
cointmp[m]=ci[i][j].coins[m]/1000;
int cnt=0;
if(j-1>=1&&ci[i][j-1].ciuse!=-1){//分给下边的点
cnt++;
for(int k=1;k<=n;k++){
ci[i][j-1].coint[k]+=cointmp[k];
}
}
if(j+1<=10&&ci[i][j+1].ciuse!=-1){//分给上边的点
cnt++;
for(int k=1;k<=n;k++){
ci[i][j+1].coint[k]+=cointmp[k];
}
}
if(i+1<=10&&ci[i+1][j].ciuse!=-1){//分给右边的点
cnt++;
for(int k=1;k<=n;k++){
ci[i+1][j].coint[k]+=cointmp[k];
}
}
if(i-1>=1&&ci[i-1][j].ciuse!=-1){//分给左边的点
cnt++;
for(int k=1;k<=n;k++){
ci[i-1][j].coint[k]+=cointmp[k];
}
}
for(int k=1;k<=n;k++){
ci[i][j].coint[k]-=cnt*cointmp[k];
}
}
void havefun(){
int flag=1;
int d=0;
while(1){
for(int i=1;i<=n;i++){
if(co[i].check(d)==0){
flag=0;
}
}
if(flag)break;
flag=1;
d++;
for(int i=1;i<=10;i++){
for(int j=1;j<=10;j++){
separate(i,j);
}
}
}
sort(co+1,co+n+1,cmp);
for(int i=1;i<=n;i++)
cout<<" "<<co[i].name<<" "<<co[i].endtime<<endl;
}
int main()
{
//freopen("in.txt","r",stdin);
int t=0;
cin>>n;
while(n!=0){
clear();
for(int i=1;i<=n;i++){
string name;
int x1,y1,x2,y2;
cin>>name>>x1>>y1>>x2>>y2;
co[i].fun(i,name,x1,y1,x2,y2);
}
cout<<"Case Number "<<++t<<endl;
havefun();
cin>>n;
}
}
不要被题目字数和代码量吓到,只要细心耐心一点,这道题还是很简单的。